我已经有了这种模式,可以防止在之前有机会完成之前调用异步方法。
我的解决方案涉及需要一个标志,然后需要锁定旗帜,感觉非常冗长。是否有更自然的方法来实现这一目标?
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;
}
}
}
}
答案 0 :(得分:2)
如评论中所述,如果您愿意,可以使用function invokeActionProcessor(functionName, message) {
const payload = {
operation: PROCESS_MESSAGE,
message,
};
const params = {
FunctionName: functionName,
InvocationType: 'Event',
Payload: new Buffer(JSON.stringify(payload)),
};
return new Promise((resolve, reject) => {
console.log("invokeActionProcessor: invoking the function " + functionName);
try {
Lambda.invoke(params, function(err, data) {
if(err) {
console.log("invokeActionProcessor: got error: " + err);
reject(err);
} else {
console.log("invokeActionProcessor: success, " + data);
resolve(null, data);
}
});
} catch (err) {
console.log("invokeActionProcessor: got exception - " + err);
}
});
}
:
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>
是return语句返回的类型。