如何在异步环境中正确使用 Fire&Forget



请考虑以下事项:

//base stuff
private readonly ConcurrentQueue<message> queue = new ConcurrentQueue<message>();
private readonly MyCacheData _cache  = new MyCacheData ();
//setuo
timer = new Timer { Interval = 60_000, AutoReset = true };
timer.Elapsed += OnTimedEvent;
httpClient.Timeout = new TimeSpan(0, 0, 60); // 60 seconds too
//
// each 60 seconds
private async void OnTimedEvent(object sender, ElapsedEventArgs e)
{
if (cache 30 minutes old)
{ 
//Fire and Forget GetWebDataAsync()
// and continue executing next stuff
// if I await it will wait 60 seconds worst case
// until going to the queue and by this time another 
// timed even fires
}
// this always should execute each 60 seconds
if (queue isnt empty)
{
process queue
}
}
// heavy cache update each 10-30 minutes
private async Task GetWebDataAsync()
{
if (Semaphore.WaitAsync(1000))
{
try
{
//fetch WebData update cache
//populate Queue if needed
}
catch (Exception)
{
}
finally
{
release Semaphore
}
}
}

彩色:https://ghostbin.com/paste/6edov

因为我作弊并使用了廉价的ConcurrentQueue解决方案,所以我不太关心GetWebDataAsync((期间会发生什么,我只想触发它并完成它的工作,同时我立即进入处理队列,因为它总是必须每60秒或计时器分辨率完成一次。

如何正确执行此操作,避免太多开销或不必要的线程生成?

编辑:在其他地方为我的案件找到答案

private async void OnTimedEvent(object sender, ElapsedEventArgs e)
{
async void DoGetWebData() => await GetWebDataAsync()
if (condition)
{ 
DoGetWebData(); // Fire&Forget and continue, exceptions handled inside
}
//no (a)waiting for the GetWebDataAsync(), we already here
if (queue isnt empty)
{
//process queue
}
}

private async Task GetWebDataAsync()
{
if (Semaphore.WaitAsync(1000))
{
try
{
//fetch WebData update cache
//populate Queue if needed
}
catch (Exception)
{
//log stuff
}
finally
{
///always release lock
}
}
}
Task.Run(...);
ThreadPool.QueueUserItem(...);

这些有什么问题吗?...

像这样的事情怎么样:

ManualResetEvent mre = new ManualResetEvent(false);
void Foo()
{
new Thread(() => 
{
while (mre.WaitOne())
{
/*process queue item*/
if (/*queue is empty*/)
{
mre.Reset();
}
}
}) { IsBackground = true }.Start();
}
void AddItem()
{
/*queue add item*/
mre.Set();
}

从另一个async方法调用async方法而不await语句

最新更新