[英]How to wait for Async Task method to finish before calling it again?
[英]How to best prevent running async method again before it completes?
我有这种模式,以防止在之前有机会完成之前调用异步方法。
我的解决方案涉及需要一个标志,然后需要锁定旗帜,感觉非常冗长。 有没有更自然的方法来实现这一目标?
public class MyClass
{
private object SyncIsFooRunning = new object();
private bool IsFooRunning { get; set;}
public async Task FooAsync()
{
try
{
lock(SyncIsFooRunning)
{
if(IsFooRunning)
return;
IsFooRunning = true;
}
// Use a semaphore to enforce maximum number of Tasks which are able to run concurrently.
var semaphoreSlim = new SemaphoreSlim(5);
var trackedTasks = new List<Task>();
for(int i = 0; i < 100; i++)
{
await semaphoreSlim.WaitAsync();
trackedTasks.Add(Task.Run(() =>
{
// DoTask();
semaphoreSlim.Release();
}));
}
// Using await makes try/catch/finally possible.
await Task.WhenAll(trackedTasks);
}
finally
{
lock(SyncIsFooRunning)
{
IsFooRunning = false;
}
}
}
}
如评论中所述,如果您愿意,可以使用Interlocked.CompareExchange()
:
public class MyClass
{
private int _flag;
public async Task FooAsync()
{
try
{
if (Interlocked.CompareExchange(ref _flag, 1, 0) == 1)
{
return;
}
// do stuff
}
finally
{
Interlocked.Exchange(ref _flag, 0);
}
}
}
那就是说,我觉得这太过分了。 在这种情况下使用lock
没有任何问题,特别是如果你不希望在方法上引起很多争用。 我确实认为倒不如说是来包装方法,使主叫方可以一直await
的结果,新的异步操作是否启动与否:
public class MyClass
{
private readonly object _lock = new object();
private Task _task;
public Task FooAsync()
{
lock (_lock)
{
return _task != null ? _task : (_task = FooAsyncImpl());
}
}
public async Task FooAsyncImpl()
{
try
{
// do async stuff
}
finally
{
lock (_lock) _task = null;
}
}
}
最后,在评论中,你这样说:
似乎有点奇怪,所有返回类型仍然对任务有效?
我不清楚你的意思是什么。 在您的方法中,唯一有效的返回类型将是void
和Task
。 如果您的return
语句返回实际值,则必须使用Task<T>
,其中T
是return语句返回的类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.