使用event唤醒异步长时间运行的作业

时间:2017-05-26 12:09:55

标签: c# events asynchronous async-await

我有一个类(Class A)负责在后台运行异步作业,如下所示:

public async void DoJob()
{
    while (true)
    {
        var thingToDo = this.getNextThing();

        if (thingToDo != null)
        {
            try
            {
                await this.performAction(thingToDo);
            }
            catch (Exception ex)
            {
                // file logging of error.
                // then wait a certain period.
                await Task.Delay(someInterval);
            }
        }
        else
        {
            // Gets the interval that should be awaited until there is a 
            // thingToDo available.
            var waitInterval = this.getWaitUntilNextThingAvailable();

            // if there such an interval then wait for it.
            if (waitInterval != null)
            {
                await Task.Delay(waitInterval.Value);
            }
            // else (basically when there is nothing to be done by this job) 
            // use an AsyncManualResetEvent to wait until its set.
            else
            {
                await this.waitHandle.WaitAsync();
            }
        }
    }
}

我基本上对上一个else块感兴趣 - 我使用AsyncManualResetEvent的块(由AsyncEx库提供)

我使用另一个类(Class B)提供的事件来设置waitHandle。这是订阅的样子(注意此方法在Class B

private event Action ChangeOccurred;

public void Attach(Action action)
{
   this.ChangeOccurred += action;
}

现在我的问题是:我使用ChangeOccurred?.Invoke()来设置waitHandle,以便可以通知Class A有事可做并继续在后台执行操作。

Invoke()是正确的方法吗?我不确定是否应该使用BeginInvoke()EndInvoke代替?该事件不包含日期,仅用作异步作业可以执行的signal

Class B中调用ChangeOccurred事件的代码是同步的。

1 个答案:

答案 0 :(得分:3)

请勿使用BeginInvoke / EndInvoke。这些方法只是在线程池线程上调用Invoke

使用myEvent?.Invoke()是提升事件的适当方式,它(同步)设置AsyncManualResetEventAsyncManualResetEvent上存在异步侦听器的事实并不重要。

另一方面,AsyncEx的最新版本(v5预览版)包括PauseToken / PauseTokenSource类型实际上只是AsyncManualResetEvent的简单包装,但可能会使代码的意图更清晰。