我需要RunWorkerAsync()
返回一个List<FileInfo>
.
能够从后台工作人员返回对象的过程是什么?
我需要RunWorkerAsync()
返回一个List<FileInfo>
.
能够从后台工作人员返回对象的过程是什么?
在您的DoWork
事件处理程序中BackgroundWorker
(这是后台工作发生的地方)有一个参数DoWorkEventArgs
. 此对象具有公共属性对象 Result。当您的工作人员生成其结果(在您的情况下为 a List<FileInfo>
)时,设置e.Result
为该结果并返回。
现在您的 BackgroundWorker 已经完成了它的任务,它会触发RunWorkerCompleted
事件,该事件有一个RunWorkerCompletedEventArgs
对象作为参数。RunWorkerCompletedEventArgs.Result
将包含您的结果BackgroundWorker
。
例子:
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
int result = 2+2;
e.Result = result;
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
int result = (int)e.Result;
MessageBox.Show("Result received: " + result.ToString());
}
我假设你不想阻塞并等待 RunWorkerAsync() 的结果(如果你这样做了,就没有理由运行异步!
如果您想在后台进程完成时收到通知,请挂钩 RunWorkerCompleted 事件。如果要返回某些状态,请在 DoWork 事件参数的 Result 成员中返回。
例子:
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
// do your thing
....
// return results
e.Result = theResultObject;
}
// now get your results
private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MyResultObject result = (MyResultObject)e.Result;
// process your result...
}
RunWorkerAsync()
异步启动进程,并在进程实际完成之前返回并继续执行您的代码。如果您想获得 的结果BackgroundWorker
,您需要创建一个实例变量来保存该值并在BackgroundWorker
完成后检查它。
如果您想等到工作完成,那么您不需要BackgroundWorker
.
为了补充大卫的答案,人们可能希望通过一个元组为方法提供多个参数。
为此,让我更新他的答案,其中一个值(称为EngagementId)通过每个调用传递,并且元组保存该原始项目以供使用以及结果。
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
var engagementId = (int)e.Argument;
int result = 2 + 2;
e.Result = (engagementId, result);
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
(int engagementId, int result) tupleResult = ((int, int)) e.Result; // Both (( are needed for tuple/casting.
MessageBox.Show($"Result received {tupleResult.result} for engagement {tupleResult.engagementId}");
}
根据您的模型,您要么希望工作线程在完成工作时回调其创建者(或其他进程),要么您必须经常轮询工作线程以查看它是否已完成,如果所以,得到结果。
等待工作线程返回其结果的想法破坏了多线程的好处。
你可以让你的线程以对象作为参数引发一个事件:
ThreadFinishedEvent(this, new ThreadEventArgs(object));
在哪里:
public class ThreadEventArgs : EventArgs
{
public ThreadEventArgs(object object)
{
Object = object
}
public object Object
{
get; private set;
}
}
一般来说,当运行异步进程时,工作线程应该调用委托或触发事件(如 ChrisF)。
您可以查看新的 PFX,它具有一些可以返回值的并发函数。
例如,有一个名为 Parallel.ForEach() 的函数,它有一个可以返回值的重载。
看看这个了解更多信息
与其在“DoWork”方法中进行后台工作,不如创建一个返回您想要返回的类型的方法,并将其应用于 e.Result,就像这里推荐的其他答案一样。作为一个最小的例子,它回答了 OP 的问题,而不会使事情过于复杂......
private List<FileInfo> FileInfoWorker(object sender, DoWorkEventArgs e)
{
return new List<FileInfo>(new DirectoryInfo("C:\\SOTest").GetFiles().ToList());
}
private void bgwTest_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
e.Result = FileInfoWorker(worker, e);
}
private void bgwTest_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
tbStatus.Text = "Background operation cancelled.";
}
else
{
tbStatus.Text = "Background operation complete.";
}
}
该示例还显示了如何从 BackgroundWorker API 更新 TextBox。未显示对通过 ProgressBar 和 TextBoxes 报告进度的支持以及对取消的支持,API 也支持这两者。代码通过按钮运行...
private void btnSOTest_Click(object sender, EventArgs e)
{
bgwTest.RunWorkerAsync();
}