SOf*_*tic 3 c# multithreading backgroundworker
我有一个BackgroundWorker为列表中的每个对象创建一个的函数,我现在想要做的是将创建的工作人员数量限制为 20,并在他们完成后处理列表中的下一项。我正在考虑使用队列,并在处理工作人员之前检查队列大小是否小于 20,然后创建工作人员并将其添加到队列中。我的问题是如何在完成后从队列中删除该项目?以及如何设置循环以等待工作人员可用?
编辑
我想我已经接近了,这就是我现在所拥有的,但问题是程序卡在了while循环中:
var myObjectList = new List<myObject>();
myObjectList = PopulateList();
BackgroundWorker bgw;
foreach (var obj in myObjectList)
{
bgw = new BackgroundWorker();
while(BgwList.Count >= 20); //getting stuck here, why?
BgwList.Add(bgw);
if(!bgw.IsBusy)
{
bgw.RunWorkerAsync(obj);
}
}
Run Code Online (Sandbox Code Playgroud)
BackgroundWorker完成后删除:
void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
BgwList.Remove((BackgroundWorker)sender); //verified that bgw is being removed from list
//... other code
}
Run Code Online (Sandbox Code Playgroud)
诚实地?不要使用BackgroundWorker. 如果您想要这种控制,请手动使用 TPL、TPL 数据流甚至反应式扩展(Rx)。
就我个人而言,我会使用 TPL 数据流,我会设置一个TransformBlock<MyObject, MyObject>您配置的MaxDegreeOfParallelism对您有意义的(例如,您想一次处理 20 个),然后将其链接回ActionBlock<MyObject>配置为在 UI 上运行的 UI 更新(Dispatcher) 线。这样的代码看起来像这样......
在初始化逻辑的某个地方,可能作为 Window 构造函数的一部分(注意:必须在主 Dispatcher 线程上执行才能正常工作)
TransformBlock<MyObject, MyObject> myProcessingBlock = new ActionBlock<MyObject, MyObject>(
myObject =>
{
// ... perform your processing of this object here ...
return myObject;
},
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 20
});
ActionBlock<MyObject> myUINotificationBlock = new ActionBlock<MyObject>(
myObject =>
{
// ... update the UI details for this data here ...
},
new ExecutionDataflowBlockOptions
{
TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext() // must be executed on the Dispatcher block!
});
myProcessingBlock.LinkTo(myUINotificationBlock);
Run Code Online (Sandbox Code Playgroud)
这就是您将新作品发布到它的方式:
MyObject someObjectToProcess = GetSomeObjectToProcess(...);
myProcessingBlock.Post(someObjectToProcess);
Run Code Online (Sandbox Code Playgroud)
剩下的一切都由 TPL 数据流库的魔力为您处理。只需声明并释放它即可。TPL Dataflow 甚至支持async方法,因此,如果您知道要进行 Web 服务调用,则只需async在您定义的方法上使用关键字即可,TransformBlock<MyObject, MyObject>如下所示:
TransformBlock<MyObject, MyObject> myProcessingBlock = new ActionBlock<MyObject, MyObject>(
async myObject =>
{
HttpClient someHttpClient = new HttpClient();
HttpResponseMessage responseMessage = await someHttpClient.PostAsync(..., ...);
return myObject;
},
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 20
});
Run Code Online (Sandbox Code Playgroud)
这样你甚至不会在HTTP网络调用未完成的情况下阻塞CPU线程,这更加充满胜利。
| 归档时间: |
|
| 查看次数: |
3512 次 |
| 最近记录: |