我必须从提供的 DLL 中调用一个例程。此 DLL 需要 2 到 10 分钟才能运行,具体取决于运行它的 PC 的速度。
我已将 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;
}
这可行,但我不能将此方法与正在等待其结果的其他调用内联调用,因为它会立即返回一个空值。
所以,我停留在一个 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
方法,以便第一个线程可以处理DoWork
代码。