代码之家  ›  专栏  ›  技术社区  ›  KreonZZ

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

  •  1
  • KreonZZ  · 技术社区  · 7 年前

    考虑以下因素:

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

    编辑: 我的案子在别处得到了答案

    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
            }
        }
    }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Jaster    7 年前
    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();
        }
    
        2
  •  0
  •   Vibeeshan Mahadeva    7 年前

    async 从另一个 异步 方法 await 陈述