我是c#的新手(也是英语),我尝试在后台并行做一些工作。我有一个包含“MyClass”对象的列表。每个都有一个“DoWork()”函数,我把这个函数放在一个列表然后我将运行所有。我有两个问题:1,这都错了吗? 2,当第一个回答是“否”时,那么是否可以设置函数的最大运行时间(当“DoWork()”花费超过600毫秒时,我想要停止它,但其他人没有。)?抱歉我的英文不好!
这是我的代码:
public class MyClass
{
static int nextId;
public int id;
public int x;
public MyClass()
{
id = Interlocked.Increment(ref nextId);
x = (id % 4 + 1) * 250;
}
public void DoWork()
{
Console.Write("start: {0}", this.id);
Thread.Sleep(x); //this simulate the work
Console.WriteLine("end: {0}", this.id);
}
}
在main中:
for (int i = 0; i < db; i++)
{
xy_list.Add(new MyClass());
}
List<Task> tasks3 = new List<Task>();
foreach (var item in xy_list)
{
Task work = new Task(() => item.DoWork());
tasks3.Add(work);
}
Parallel.ForEach(tasks3, task =>
{
task.Start();
});
答案 0 :(得分:2)
你需要自己做一些工作。取消任务是一个合作过程(有关更多信息,请参阅Cancellation in Managed Threads)。
为了能够取消后台任务并让它们超时,您需要创建一个超时的CancellationTokenSource
。此令牌源可用于为您正在启动的任务提供取消令牌,您还需要将它们传递给DoWork
方法,该方法应检查是否请求取消。
如果您构建了具有超时的取消令牌源,它将在超时到期时发出所有已连接的取消令牌的信号。
在你的代码示例中使用它会使它看起来像这样:
public class MyClass
{
static int nextId;
public int id;
public int x;
public MyClass()
{
id = Interlocked.Increment(ref nextId);
x = (id % 4 + 1) * 250;
}
public void DoWork(CancellationToken cancelToken)
{
bool is_canceled = false;
while (!cancelToken.IsCancellationRequested && cycle < 5)
{
try
{
Console.WriteLine("Task {0} waiting, tid = {1}", id, Thread.CurrentThread.ManagedThreadId);
Task.Delay(x / 5, cancelToken).Wait(); // don't do Thread.Sleep()
Console.WriteLine("Task {0} waking up, tid = {1}", id, Thread.CurrentThread.ManagedThreadId);
}
catch (AggregateException ex)
{
if (ex.InnerExceptions.Any(x => typeof(OperationCanceledException).IsAssignableFrom(x.GetType())))
{
Console.WriteLine("Task {0} canceled, tid = {1}", id, Thread.CurrentThread.ManagedThreadId);
is_canceled = true;
break;
}
throw;
}
catch (OperationCanceledException)
{
Console.WriteLine("Task {0} canceled, tid = {1}", id, Thread.CurrentThread.ManagedThreadId);
is_canceled = true;
}
cycle++;
}
is_canceled |= cycle < 5;
Console.WriteLine("{0} {1}, tid = {2}", this.id, is_canceled ? "canceled" : "completed", Thread.CurrentThread.ManagedThreadId);
}
}
在你的&#34; main&#34;:
for (int i = 0; i < db; i++)
{
xy_list.Add(new MyClass());
}
// set cancellation timeout for 600 ms.
var cancelSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(600));
// start all tasks
List<Task> tasks3 = new List<Task>();
foreach (var item in xy_list)
tasks3.Add(Task.Run(() => item.DoWork(cancelSource.Token), cancelSource.Token));
// Wait for all tasks to be finished.
Task.WaitAll(tasks3.ToArray());