![](/img/trans.png)
[英]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.