提供されているDLLからルーチンを呼び出す必要があります。このDLLは、実行されているPCの速度にもよりますが、実行に2〜10分かかります。
インターフェイスが応答し続けるように、DLL呼び出しをBackgroundWorkerスレッドに入れました。
private object Load(string feature) {
object result = null;
using (var w = new BackgroundWorker()) {
w.WorkerReportsProgress = true;
w.WorkerSupportsCancellation = true;
w.DoWork += delegate(object sender, DoWorkEventArgs e) {
e.Result = DAL.get(feature);
};
w.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e) {
progressBar1.Visible = false;
if (e.Error != null) {
MessageBox.Show(this, e.Error.Message, "Load Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
} else {
result = e.Result;
}
};
w.RunWorkerAsync();
if (w.IsBusy) {
progressBar1.Style = ProgressBarStyle.Marquee;
progressBar1.Visible = true;
}
}
return result;
}
これは機能しますが、結果を待っている他の呼び出しとインラインでこのメソッドを呼び出すことはできません。これは、すぐにnull値を返すためです。
そのため、ManualResetEventインスタンスを使用して、メソッドが実際に値を取得するまで待機してから、次の値を返すようにしました。
private object Load(string feature) {
object result = null;
using (var w = new BackgroundWorker()) {
var mre = new ManualResetEvent(false);
w.WorkerReportsProgress = true;
w.WorkerSupportsCancellation = true;
w.DoWork += delegate(object sender, DoWorkEventArgs e) {
e.Result = DAL.get(feature);
};
w.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e) {
progressBar1.Visible = false;
if (e.Error != null) {
MessageBox.Show(this, e.Error.Message, "Model Load Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
} else {
result = e.Result;
}
mre.Set();
};
w.RunWorkerAsync();
if (w.IsBusy) {
progressBar1.Style = ProgressBarStyle.Marquee;
progressBar1.Visible = true;
progressBar1.Value = 0;
const string statusRun = @"\|/-";
const string statusMsg = "Loading Data...";
int loops = 0;
do {
int index = loops++ % 4;
tsStatus.Text = statusMsg + statusRun[index].ToString(); // '\', '|', '/', '-'
} while (!mre.WaitOne(200));
}
}
return result;
}
ただし、これを行うと、CPU時間がすべてManualResetEventのWaitOne
メソッドに費やされ、Set()
トリガーが呼び出されないようです。
誰かが以前にこの動作に遭遇し、それに対する良い回避策を見つけたことがありますか?
過去に回避策を作成しましたが、最初のスレッドがコードWaitOne
を処理できるように、メソッドを実行するための2番目のスレッドを作成する必要がありました。DoWork