异步 - 留在当前线程上? [英] async - stay on the current thread?

查看:26
本文介绍了异步 - 留在当前线程上?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读过 Eric lippert 的 文章 关于 async 以及人们对 async 的困惑关键词.他说:

I've read Eric lippert's article about async , and about confusions people had with async keyword. he said :

it (async) 表示此方法包含涉及等待的控制流异步操作,因此将被重写编译器进入延续传递风格,以确保异步操作可以在正确的位置恢复此方法."异步方法的全部意义在于您尽可能多地停留在当前线程上

it (async) means "this method contains control flow that involves awaiting asynchronous operations and will therefore be rewritten by the compiler into continuation passing style to ensure that the asynchronous operations can resume this method at the right spot." The whole point of async methods it that you stay on the current thread as much as possible

我不明白这个.如果我执行一个异步方法 (Task) 并且它运行,它肯定在另一个线程上运行.

I don't understand this. If I execute an asynchronous method (Task) and it runs , it surely runs on another thread.

此外,如果我编写一个使用 await 的方法,(恕我直言)它会释放正常的控制流,并且代码被重构类似ContinueWith" 稍后,在另一个线程上.

Moreover , If I write a method uses await , (imho) it releases the normal control flow , and code is refactored alike "ContinueWith" later , on another thread.

我用(控制台)测试过:

I tested it with (console) :

/*1*/   public void StartChain()
/*2*/   {
/*3*/           var a = FuncA();
/*4*/           Console.WriteLine(a.Result);
/*5*/   }
/*6*/   
/*7*/   public async Task < int > FuncA()
/*8*/   {
/*9*/           Console.WriteLine("A--" + Thread.CurrentThread.ManagedThreadId);
/*10*/           var t = await FuncB();
/*11*/           Console.WriteLine("B--" + Thread.CurrentThread.ManagedThreadId);
/*12*/           return t;
/*13*/   }
/*14*/   
/*15*/   public async Task < int > FuncB()
/*16*/   {
/*17*/           Console.WriteLine("C--" + Thread.CurrentThread.ManagedThreadId);
/*18*/           await Task.Delay(2000);
/*19*/           Console.WriteLine("D--" + Thread.CurrentThread.ManagedThreadId);
/*20*/           return 999;
/*21*/   }
/*22*/   
/*23*/   void Main()
/*24*/   {
/*25*/           StartChain();
/*26*/   }
/*27*/   

结果是:

A--7
C--7
D--17         <-----D  and B are on different thread
B--17
999

那么埃里克所说的留在当前线程上"是什么意思?

So what did Eric mean by saying "stay on the current thread"?

asp.net 中,它也返回不同的线程 ID.

in asp.net it also return differnt thread ID.

public async Task<int> FuncA()
{
    Response.Write("<br/>C----" + Thread.CurrentThread.ManagedThreadId);
    var t = await FuncB();
    Response.Write("<br/>D----" + Thread.CurrentThread.ManagedThreadId);
    return t;
}

public async Task<int> FuncB()
{
    Response.Write("<br/>E----" + Thread.CurrentThread.ManagedThreadId);
    await Task.Delay(2000);
    Response.Write("<br/>F----" + Thread.CurrentThread.ManagedThreadId);
    return 999;
}



protected async void Page_Load(object sender, EventArgs e)
{
    Response.Write("<br/>A----" + Thread.CurrentThread.ManagedThreadId);
    var a=await FuncA();
    Response.Write("<br/>B----" + Thread.CurrentThread.ManagedThreadId);

}

A----8
C----8
E----8
F----9
D----9
B----9

编辑 2

(得到答案后)

似乎线程仅在 GUI 应用程序中提供:.我在 winform 运行此代码

  public async Task<int> FuncA()
        {
            textBox1.Text +=Environment.NewLine+ "
C----" + Thread.CurrentThread.ManagedThreadId;
            var t = await FuncB();
            textBox1.Text += Environment.NewLine + "
D----" + Thread.CurrentThread.ManagedThreadId;
            return t;
        }

        public async Task<int> FuncB()
        {
            textBox1.Text += Environment.NewLine + "
E----" + Thread.CurrentThread.ManagedThreadId;
            await Task.Delay(2000);
            textBox1.Text += Environment.NewLine + "
F----" + Thread.CurrentThread.ManagedThreadId;
            return 999;
        }




        private async void Form1_Load(object sender, EventArgs e)
        {
            textBox1.Text += Environment.NewLine + "
A----" + Thread.CurrentThread.ManagedThreadId;
            var a = await FuncA();
            textBox1.Text += Environment.NewLine + "
B----" + Thread.CurrentThread.ManagedThreadId;
        }

推荐答案

添加了 async/await 支持以帮助程序员编写不会冻结的 GUI.WinRT 在应用商店应用中特别有用,也是它被添加到 C# v5 的核心原因,它是一个非常不友好的 api,它具有许多异步方法.

The async/await support was added to help programmers write GUIs that don't freeze. Particularly useful in Store apps, and the core reason it was added to C# v5, WinRT is a pretty unfriendly api that has many asynchronous methods.

保持在同一线程上"场景在 GUI 应用程序中非常很重要,这是必需的,因为 GUI 不是线程安全的.然而,它确实需要一个调度程序循环(又名 Application.Run),这是让异步代码在同一线程上恢复的唯一方法.该循环是生产者-消费者问题的核心解决方案.

The "stay on the same thread" scenario is very important in a GUI app, required because a GUI isn't thread-safe. It does however require a dispatcher loop (aka Application.Run), the only way to get asynchronous code to resume on the same thread. That loop is the core solution to the producer-consumer problem.

显然你的程序没有,看起来很像一个控制台模式的应用程序.因此,您不会得到这种行为,它会在工作线程上恢复.

Clearly your program doesn't have one, looks a lot like a console mode app. You therefore don't get this behavior, it resumes on a worker thread.

没什么大问题,您实际上不需要它在同一线程上恢复,因为无论如何控制台都是线程安全的.嗯,大多数情况下,当您要求输入时,不包括在 .NET 4.5 中添加的锁.这当然也意味着您也没有大量使用 async/await,Task 也可以正常工作.

Not much of a problem, you don't actually need it to resume on the same thread since a console is thread-safe anyway. Well, mostly, not counting the lock that was added in .NET 4.5 when you ask for input. Which of course also means that you don't have a heckofalot of use for async/await either, a Task works fine as well.

这篇关于异步 - 留在当前线程上?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆