【问题标题】:How to run possibly synchronous or possibly asynchronous code?如何运行可能同步或可能异步的代码?
【发布时间】:2014-12-31 12:38:31
【问题描述】:

我有一个带有一些异步方法的类,它们采用处理程序类来决定成功或失败时要做什么。

public class FooModel
{
    private FooState fooState;

    public async Task UpdateFooAsync(IHandler handler)
    {
        try
        {
            var newFooState = await Something();
            fooState = newFooState;

            handler.Success();
        }
        catch
        {
            handler.Error();
        }
    }
}

public interface IHandler
{
    void Success();
    void Error();
}

我可能会从代码中的几个不同位置调用 UpdateFooAsync。根据我从哪里调用它,我可能想做不同的事情。比如一个同步的例子:

public async void update_click(object sender, RoutedEventArgs e)
{
    await UpdateFooAsync(new Handler1());
}

public class Handler1 : IHandler
{
    public void Success()
    {
        Provider.Page.text = "hello";
    }
    public void Error() {}
}

但我可能还想做一个异步操作:

private async void updateAndThenSomething_click(object sender, RoutedEventArgs e)
{
    await UpdateFooAsync(new Handler2());
}

// this will generate not implemented error obviously
public class Handler2 : IHandler
{
    public async void SuccessAsync()
    {
        await Provider.OperationAsync();
    }
    public void Error() {}
}

但是 FooModel 不知道我接下来是要进行同步还是异步操作。它不应该知道。有没有办法让 handler.Success() 运行同步代码或异步代码?我阅读了 Stephen Toub 的一些资料 (link),这似乎暗示我不应该将 Success 设为 Task,然后在 UpdateFooAsync try 块中等待该任务。

我猜另一种选择是完全放弃处理程序接口。但这需要大量的重构。上述情况在我的代码中经常发生,通常不仅仅是成功和错误。我想强制某人使用我的代码来指定成功、错误或其他情况时会发生什么。这就是我使用界面的原因。我想我也可以通过抛出不同类型的异常来做到这一点,但我也不确定这是否是个好主意。

【问题讨论】:

  • @ghord 我只是查了一下意思。这是为了让线程不会回到 UpdateFooAsync 方法或 updateAndThenSomething_click 方法吗?后者是因为它是异步无效的吗?如果我要在 handlerSuccess() 下添加其他代码或 await UpdateFooAsync(new Handler2()) 怎么办? 编辑:我猜评论被删除了

标签: c# asynchronous


【解决方案1】:

您可以声明您的处理程序接口以返回Task,然后在同步情况下使用Task.FromResult 返回。例如

public interface IHandler
{
    Task Success();
    void Error();
}

public class Handler1 : IHandler
{
    public Task Success()
    {
        Provider.Page.text = "hello";
        return Task.FromResult<object>(null); 
    }
    public void Error() {}
}

public class Handler2 : IHandler
{
    public async Task Success()
    {
        return Provider.OperationAsync();
    }

    public void Error() {}
}

【讨论】:

  • 这似乎是一个非常简单的解决方案,谢谢。您是否建议根据 .NET 约定将名称更改为 SuccessAsync,或者在这种情况下不需要这样做?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-18
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
相关资源
最近更新 更多