【问题标题】:Async methods Explanation异步方法说明
【发布时间】:2015-10-05 20:11:16
【问题描述】:

好的,所以我是 async、await 和 Task 的新手,所以我玩了一下并用 Google 搜索,但我不太确定它是如何工作的以及它应该如何实现 所以让我先给出我的代码

public class MessageQuery
{
    public byte[] Buffer { get; set; }
}

public class MessageQuery<T> : MessageQuery
{
    private SocketLayer _socketLayer;
    private readonly ManualResetEvent _wait = new ManualResetEvent(false);
    public MessageQuery(SocketLayer socketLayer)
    {
        this._socketLayer = socketLayer;
    }

    public Task<T> Execute()
    {
        _wait.Reset();//Set the wait
        var task = new Task<T>(SendAndWait);
        task.Start();
        return task;
    }

    private T SendAndWait()
    {
        _socketLayer.ExecuteQuery(this);
        _wait.WaitOne();
        //Deserialize recieved bytes to T
        return default(T);
    }

}

public class SocketLayer
{
    public MessageQuery<T> BuildTask<T>(/*some parameters*/)
    {
        //Build the message query from all parameters

        return new MessageQuery<T>(this);
    }


    public void ExecuteQuery(MessageQuery query)
    {
        //Using Sockets send Buffer
        //Another Thread will listen and receive buffers, with using SequenceId's it will notify the correct MessageQuery to be completed with the result
    }
}

public class GlobalAccess
{
    readonly SocketLayer _layer = new SocketLayer();
    public Task<List<Client>> LoadedClients { get; set; }
    public Task<List<Client>> GetAllClients()
    {
        if (LoadedClients != null)
        {
            var task = _layer.BuildTask<List<Client>>();
            LoadedClients = task.Execute();
        }
        return LoadedClients;
    }
}


public class SomeForm
{
    readonly GlobalAccess _access = new GlobalAccess();

    //Approach I am not using currently
    async void Button_whateverClickWithAsync(/*parameters*/)
    {
        var clients = await _access.GetAllClients();
        //Do whatever
    }

    //Approach I am using currently
    void Button_whateverClickWithoutAsync(/*parameters*/)
    {
        _access.GetAllClients().ContinueWith(HandleResult);
        //Do whatever
    }

    private void HandleResult(Task<List<Client>> x)
    {
        //Using Dispatcher to Do whatever
    }
}

上面的代码只是对我如何设计我的类的“简化”解释,它不仅仅是这个,但它应该给你一个想法。 现在我目前在 wpf 和 Xamarin 中使用它并且效果很好,但是在 Xamarin 中我开始使用 Task 而不是 Thread 因为 PCL 只有 Task 在,这让我和 Idea 使用上面的模式重写部分代码(部分完成)但是我不完全理解异步/等待,使用上面的代码将是更好的使用方法,或者有更好的方法可以采用

【问题讨论】:

  • 写一段简单的异步代码,通过反编译器看看结果(或者看看这个页面>>community.sharpdevelop.net/blogs/danielgrunwald/archive/2012/04/…)。Async 和 await 只是“语法糖”——一种创建以多线程方式执行的“线性”代码的简单方法。
  • 我不确定我是否真的理解你的问题。你能澄清一下吗?
  • @Matt async-await 比“语法糖”复杂得多。
  • 我的问题是异步的最佳方法是什么
  • @DonaldJansen 这有点宽泛。 “最佳方法”是什么意思?

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


【解决方案1】:

Await = 执行在此时停止,您的程序会执行其他操作,直到 await 任务完成。 然后在 await 行的正下方继续执行。

async void = 对于事件,无需等待。

任务 t = blaAsync = INSTANT START(您可以稍后使用 t.wait 等待)

【讨论】:

    【解决方案2】:

    您似乎正在考虑使用 ContinueWith 与使用 async-await 的显式延续。

    我绝对更喜欢后者,因为它会导致代码更简洁。它有效地允许您运行异步代码,同时将其视为同步代码,这为您尝试做的事情增加了很多清晰度:

    async void Button_whateverClickWithAsync(/*parameters*/)
    {
        var clients = await _access.GetAllClients();
        // Here, you execute the rest of your code as if
        // running synchronously.
    }
    
    void ButtonClick(/*parameters*/)
    {
        _access.GetAllClients().ContinueWith(HandleResult);
        // When does the continuation run? What happens if you want
        // to execute this only if the task fails?
    }
    

    这确实归结为编码偏好。如果您选择使用async-await,您应该更多地了解它并了解当方法被标记为async 时实际发生的情况。

    【讨论】:

    • 所以我现在理解的不仅是 await 更干净,而且实际上比使用 ContinueWith(xx) 更安全
    • 不,这与“安全”无关,更多的是关于可读性。如果您想处理在Task 中发生的异常,您可以使用await Task 并将其包装在try-catch 中,就像同步代码一样。而使用ContinueWith,您必须在委托内部处理它,这感觉不太自然。
    【解决方案3】:

    我发现await的最佳思路如下:

    首先,想一想要执行的这个简单的列表函数,一次一个:

    DoSomething();
    SomethingElse();
    OneLastThing();
    

    现在,当您添加等待时:

    await DoSomething();
    SomethingElse();
    OneLastThing();
    

    考虑它的一个好方法是,就好像编译器实际上为你生成了这个伪代码:

    Start Task() => { DoSomething(), OnCompleted = TaskCompletedCallback };
    
    //Once the task has finished, after an unknown amount of time
    //call this sort-of auto-generated callbcak
    private void TaskCompletedCallback()
    {
        SomethingElse();
        OneLastThing();
    }
    

    请记住,这不是真正正在发生的事情,只是一个很好的方式来绕过它。

    【讨论】:

    • 这是有道理的,所以我基本上可以说使用await更干净,最终更容易维护
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    • 2017-05-22
    • 2018-01-25
    • 1970-01-01
    • 1970-01-01
    • 2019-03-25
    • 2020-10-31
    相关资源
    最近更新 更多