我正在使用Multithreading
来解决我的问题。我一直在后台工作程序Parallel.Foreach
事件中使用DoWork
,其中长时间运行的作业一直在执行。但是,当我必须取消这项工作时,问题就出现了。它不会立即取消线程。
BackgroundWorker DoWork活动:
private void File_DoWork(object sender, DoWorkEventArgs e)
{
var cts = new CancellationTokenSource();
btnCancel.Click += (cancelSender, cancelEvent) =>
{
bgwFile.CancelAsync();
if (bgwFile.CancellationPending)
{
cts.Cancel();
e.Cancel = true;
}
};
object sync = new object();
List<Response> responses = null;
var parallelOperation = new ParallelOptions
{
MaxDegreeOfParallelism = 3,
CancellationToken = cts.Token
};
Parallel.ForEach(listRequest, parallelOperation, request =>
{
lock (sync)
{
responses = GetQueryResponse(request); // Long running process
parallelOperation.CancellationToken.ThrowIfCancellationRequested();
}
});
e.Result = responses ;
}
这里,问题是我必须取消长时间运行的工作。假设有三个请求已经循环并行。有MaxDegreeOfParallelism = 3
,然后它用于GetQueryResponse(request)
方法,这是一个很长的工作,如果我使用CancellationTokenSource
取消线程,那么它不会立即取消该过程。它只在执行3个请求线程后取消。
我希望立即取消它。是否有任何方法可以立即取消由Parallel.Foreach
生成的所有正在运行的线程并转到后台工作的RunWorkerCompleted
事件?
答案 0 :(得分:3)
您可以使用CancellationToken.Register
Method (Action) 注册在取消CancellationToken
时将被调用的代理。
请求取消后会立即解雇。当然,您必须编写将立即导致当前GetQueryResponse
执行停止的逻辑。
答案 1 :(得分:0)
检查TPL的CancellationTokens。here将CancellationToken传递给Parallel.Foreach()可以使它工作。当您想要停止所有任务时,只需使用:
cts.Cancel()
在Task的方法位置
cts.Token.ThrowIfCancellationRequested(); 当你想检查是否需要停止任务,因为另一个任务取消了该过程。
答案 2 :(得分:-2)
您可以将线程的IsBackground属性设置为true。当你的应用程序完成时,这将终止所有线程。
您可以使用一个定时器(或一个线程)来唤醒并检查数据。这应该更加资源友好。