1

考虑以下:

//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
        }
    }
}
4

2 回答 2

1
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();
    }
于 2018-08-14T10:38:24.210 回答
0

async从另一个async方法调用一个方法而不用 await声明

于 2018-08-14T10:30:24.247 回答