我有以下代码:
Thread validationThread = new Thread(DoAsyncValidationMethod);
validationThread.Start(threadParams);
bool isAborted = false;
int timeLeft = 5000;
// wait for thread terminates itself
if (!validationThread.Join(timeLeft))
{
// timeout, abort thread
validationThread.Abort();
isAborted = true;
}换句话说,我正在做一些应该在指定的时间间隔(5000毫秒)内完成的工作。如果完成或未完成,采用的线程方法将保证代码在启动后不晚于5秒返回。
有没有一种方法可以通过异步/等待模式来实现这一点?或者,既然线程只是用来玩把戏的,有没有其他方法可以采取呢?
越优雅、越简单越好。谢谢你的帮助。
发布于 2017-07-07 09:43:06
这是我在一个项目中使用的一段代码。
此外,还可以查看[MSDN上的Task.WhenAny(参数Task[]任务)方法](https://msdn.microsoft.com/en-us/library/hh194796(v=vs.110%29.aspx)。它返回已完成的任务。
var timeout = 5000;
var task = Task.Run(() => {
Thread.Sleep(new Random().Next(3000, 7000));//Running time simulation!
return "Say my name!";//Breaking Bad!
});
if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
// Task completed within timeout.
// What if the task is faulted or canceled.
// I did not supply a cancellation token but it can easily be added
// We re-await the task so that any exceptions/cancellation is rethrown.
await task;
}
else {
// timeout/cancellation logic
}发布于 2017-07-07 16:14:05
使用CancellationTokenSource。来源是CancellationTokens的一家工厂。您可以将此令牌传递给您希望能够以一种整洁的方式取消其处理的每个人。当您想要取消具有来自同一CancellationTokenSource的CancellationToken的所有进程时,只需告诉CancellationTokenSource向它产生的所有CancellationTokens发送取消,从而取消具有来自此来源的令牌的所有进程。
更好的是,CancellationTokenSource有一个CancelAfter(some timeout)。
让进程启动器为您提供cancellationToken是一种好的做法,这样您的进程启动器就可以在一次调用中决定要取消哪些进程。
public async Task<MyResult> MyProcessAsync(CancellationToken cancellationToken, ...)
{
// do something lengthy processing, without await, regularly check if Cancellation requested
while (stillProcessing)
{
cancellationToken.ThrowIfCancellationRequested();
... // process
}
// do some processing with async-await:
await myDbContext.SaveChangesAsync(cancellationToken);
}用法:
private async Task LengthyProcessing(...)
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
tokenSource.CancelAfter(TimeSpan.FromSeconds(5));
CancellationToken myCancellationToken = tokenSource.Token
try
{
// Start one task, don't await yet:
var myTask = await MyProcessAsync(myCancellationToken, ...)
// during processing there will be regular check if cancellation requested
// meanwhile, whenever myTask has to await, I can do some processing
// I'll have to check for cancellation regularly also:
while(...)
{
myCancellationToken.ThrowIfCancellationRequested();
DoSomeProcessing();
...
}
MyResult result = await myTask;
// if here, not cancelled. can use Result:
ProcessResult(result);
}
catch (OperationCanceledException exc)
{
ProcessOperationCanceled();
}
}请注意,仅使用了一个CancelltionTokenSource。每当这个源认为某些东西应该被取消时,所有拥有来自这个源的令牌的线程都会收到关于取消请求的通知。
考虑使用bool CancellationToken.IsCancellationRequested,而不是通过CancellationToken.ThrowIfCancellationRequested()使用异常处理。
发布于 2017-07-07 10:26:34
你可以用微软的Reactive Framework (NuGet "System.Reactive")很好地做到这一点。然后你可以这样做:
IObservable<bool> query =
Observable.Amb(
Observable.Timer(TimeSpan.FromSeconds(5.0)).Select(_ => false),
Observable.Start(() => DoAsyncValidationMethod()).Select(_ => true));
IDisposable subscription =
query.Subscribe(flag =>
{
/* `true` succeeded, `false` timed out */
});https://stackoverflow.com/questions/44960906
复制相似问题