【发布时间】:2017-07-28 04:47:24
【问题描述】:
我正在使用以下方法创建新的Tasks,并在后台进行长时间的操作。如果满足某个条件,我需要完全停止所有任务并向用户显示消息。
dowork()
{
mylist = new List<DataModel.CheckData>();
int index = 0;
foreach (var line in mylist)
{
mylist.Add(new DataModel.CheckData() { RawLine = line, data = line,FileName=virtualfilelist[index].ToString() });
index++;
}
BlockingCollection<DataModel.CheckData> ujobs = new BlockingCollection<DataModel.CheckData>();
timerRefreshUi.Start();
Task.Factory.StartNew(() =>
{
_dtRows.Clear();
uiQueue.Clear();
uiQueueBad.Clear();
uiQueueGood.Clear();
for (int i = 0; i < mylist.Count; i++)
{
AddResultRow(mylist[i].data, "Waiting...",mylist[i].FileName, Color.White);
ujobs.TryAdd(new DataModel.CheckData() { RowId = i, data = mylist[i].data }, 1000);
}
List<Task> openCheckTasks = new List<Task>();
while (ujobs.Count > 0)
{
while (openCheckTasks.Where(task => task.Status == TaskStatus.Running).ToList().Count >= threadcount)
System.Threading.Thread.Sleep(250);
Task t = new Task(new Action(() =>
{
}));
openCheckTasks.Add(t);
t.Start();
}
Task.WaitAll(openCheckTasks.ToArray());
}).ContinueWith(task => {
_benchmark.Stop();
this.BeginInvoke(new Action(() =>
{
}));
});
}
我曾尝试在 while 循环中使用 Cancellation Token 和 break。但它无法正常工作。请建议停止所有线程的最佳方法。我对多线程编程的经验很少。
【问题讨论】:
-
那里有一个很好的答案。请记住,从根本上说,线程没有完全可靠的方法来停止。在 .net 和 java 中都没有。所有“答案”都是绕过这种行为的技巧。如果 (1) 您的后台任务超过(例如)10 秒,并且 (2) 您需要确定性地停止它们,并且 (3) 在任何给定时间您不会有成千上万的此类任务在运行,请考虑
processover thread . -
为什么要限制创建的任务数量? TPL 已经在调度方面做得很好,并且您受限于 PC 上的内核数量,以及可以同时处理多少个任务。循环内的
System.Threading.Thread.Sleep(250);不是一个非常有用的模式。 -
您实际上是在尝试以有限的并行度来处理您的项目。 .NET 已经为此提供了工具(它们也支持协作取消):
Parallel.ForEach和/或 TPL 数据流。 -
CancellationToken是你的朋友 - 查看 MSDN 了解更多信息,伙计。 -
您使用任务的方法有尊重取消令牌。你不能简单地停止任务(就像你可以用线程做的那样),你必须添加逻辑来检查令牌inside你的状态产生任务的方法。
标签: c# .net multithreading winforms task