使用await实现CancelEventArgs的事件

时间:2013-04-19 16:08:24

标签: c# task-parallel-library async-await

我有一个类似的基类:

public abstract class PageBase
{
    public PageBase() { }

    public Task<object> Refresh(ModelRequirements requirements)
    {
        // does work of talking to server and getting data
    }

    private DataStates _dataState;
    public DataStates DataState()
    {
        get { _dataState = value; }

        set
        {
            var e = new DataStateChangingEventArgs();

            // the following method raises the changing event.
            // it does not return a task, and cannot be awaited.
            OnDataStateChanging(e);

            if (e.Cancel)
                return;

            _dataState = value;
        }
    }

    public event EventHandler<DataStateChangingEventArgs> DataStateChanging;
    protected virtual void OnDataStateChanging(DataStateChangingEventArgs e)
    {
        var dataStateChanging = DataStateChanging;
        if (DataStateChanging != null)
            DataStateChanging(this, e);
    }
}

我实现了这样一个页面:

public class ContactsSearchPage : PageBase
{
    public ContactsSearchPage() { }

    private ContactModel Model {get; set;}

    protected async override void OnDataStateChanging(DataStateChangingEventArgs e)
    {
        // make new requirements
        var contactRequirements = new ContactRequirements();

        // Because the Refresh is awaited, it returns here and the rest 
        // of the DataState setter executes
        var refreshResult = await Refresh(contactRequirements);

        // set the property
        Model = refreshResult as ContactModel;

        // if the server returned null don't allow the data-state change to proceed
        if (Model == null)
            e.Cancel = true;
    }
}

等待刷新(在OnDataStateChanging覆盖内)是一个问题,因为它返回。在不使OnDataStateChanging返回Task的情况下,是否有这种模式的解决方案?

1 个答案:

答案 0 :(得分:2)

期望属性设置器实际设置属性,并且它将在setter返回之前执行此操作。违反这种期望会引起混淆。

  

有这种模式的解决方案吗?

我建议将属性更改为getter,以及处理set的方法:

public DataStates DataState { get; private set; }

public Task UpdateDataStateAsync()
{
   // ... Use await as necessary

这将使您的API与内部实际发生的内容相匹配,并且更容易理解。