我读过Eric lippert关于<code>异步关键字的困惑。他说:
它(async
)意味着“此方法包含包含等待异步操作的控制流,因此将由编译器重写为连续传递样式,以确保异步操作可以在正确的位置恢复此方法。”异步方法的关键在于尽可能多地停留在当前线程上
这个我不懂。如果我执行一个异步方法(< code>Task)并且它运行了,那么它肯定会在另一个线程上运行。
此外,如果我编写一个方法使用wait
,(imho)它会释放正常的控制流,并且代码在另一个线程上被重构为“ContinueAnd
”。
我用(控制台)测试了它:
/*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
那么,Eric说“留在当前线程上”是什么意思呢?
在< code>asp.net中,它还返回不同的线程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
(得到答案后)
似乎线程仅在GUI应用程序中提供:。我在winform中运行此代码
public async Task<int> FuncA()
{
textBox1.Text +=Environment.NewLine+ "\nC----" + Thread.CurrentThread.ManagedThreadId;
var t = await FuncB();
textBox1.Text += Environment.NewLine + "\nD----" + Thread.CurrentThread.ManagedThreadId;
return t;
}
public async Task<int> FuncB()
{
textBox1.Text += Environment.NewLine + "\nE----" + Thread.CurrentThread.ManagedThreadId;
await Task.Delay(2000);
textBox1.Text += Environment.NewLine + "\nF----" + Thread.CurrentThread.ManagedThreadId;
return 999;
}
private async void Form1_Load(object sender, EventArgs e)
{
textBox1.Text += Environment.NewLine + "\nA----" + Thread.CurrentThread.ManagedThreadId;
var a = await FuncA();
textBox1.Text += Environment.NewLine + "\nB----" + Thread.CurrentThread.ManagedThreadId;
}
Eric Lippert的“线程”术语被简化了。我的博客上有一个<code>异步/<code>等待
如果您在UI上下文中,则该上下文是单个UI线程,并且< code>async方法将在该线程上继续。否则,规则就有点复杂了。特别是,控制台应用程序不提供任何上下文,所以默认情况下< code>async方法在线程池上恢复。
添加了异步/等待支持,以帮助程序员编写不会冻结的 GUI。WinRT 在应用商店应用中特别有用,也是将其添加到 C# v5 的核心原因,它是一个非常不友好的 API,具有许多异步方法。
“保持在同一线程上”场景在GUI应用程序中非常重要,这是必需的,因为GUI不是线程安全的。然而,它确实需要调度程序循环(又名Application.Run),这是让异步代码在同一线程上恢复的唯一方法。该循环是生产者-消费者问题的核心解决方案。
很明显,您的程序没有,看起来很像控制台模式的应用程序。因此,您不会得到这种行为,它会在工作线程上恢复。
没什么大问题,你实际上不需要它在同一个线程上恢复,因为无论如何控制台都是线程安全的。嗯,主要是,不包括在. NET 4.5中添加的锁。当您要求输入时。这当然也意味着您也没有async/wait的用途,任务也可以正常工作。
如果我执行一个异步方法并运行它,它肯定会在另一个线程上运行。
不,它通常在另一个线程上运行。它不一定在另一个线程上运行。
暂时停止考虑线程,考虑异步的本质。异步的本质是:
假设你在做你的税务工作,在这个复杂的工作流程中,你需要执行大量的额外任务。你可以做一些手术,然后记住你在哪里,然后去吃午饭。然后回来再做几次手术,然后记住你在哪里,然后喂猫。然后回来再做几次手术,然后记得你在哪里,洗盘子。然后完成计算,然后继续您在工作流程中停止的位置。
这是一个异步计算,但只需要一个工作人员来完成。拥有多个工作人员只是执行异步的一种特别方便的方法,不是必须的。
我知道使用无线程异步有更多线程可用于服务输入(例如HTTP请求),但我不明白当异步操作完成并且需要一个线程来运行它们的延续时,这如何不可能导致线程饥饿。 假设我们只有3个线程 并且它们在需要线程的长时间运行的操作中被阻塞(例如在单独的db服务器上进行数据库查询) 使用async Wait,您可以 然而,在我看来,这可能会导致“正在进行”的异步操作过剩,如果太多的操作同时完成,那么就没有线程可以运行
线程中使用 java.lang.Runnable 如果用户在代码中通过 java.lang.Runnable 新启动了线程或者采用了线程池去异步地处理一些业务,那么需要将 SOFATracer 日志上下文从父线程传递到子线程中去,SOFATracer 提供的 com.alipay.common.tracer.core.async.SofaTracerRunnable 默认完成了此操作,大家可以按照
正在使用和原始人的线程吗? 许多月前,我学会了如何在Android上编写多线程Java代码。我记得我必须创建线程、启动线程等等。 现在我正在学习Javascript,我刚刚学习了和。 例如: 这看起来比我以前做的简单多了,而且更直观。 将首先启动,然后启动快速函数(),然后将等待,直到两个函数在日志记录之前解决-和和可能同时运行。我希望这最终取决于浏览器是否是独立的线程。但看起来它走路和说话就像粗
Dart 的库充满了返回 Future 或 Stream 对象的函数。这些函数是“异步的”:它们在设置一个可能比较耗时的操作(比如 I/O)后返回,而不去等待操作完成。 关键字 async 和 await 支持异步编程,可以使你用看起来像同步的方式编写异步代码。 处理 Futures 当你需要一个已完成的 Future 的结果时,你有两个选择: 使用 async 和 await。 使用 Futur
因为我们知道progressdialog需要一个参数上下文或获取片段的活动,但在解除对话框后,它转到了另一个片段,我将其设置为mainactivity默认片段为homepage 这是我课堂上使用的方法
我正在为一个大型应用程序编写自动化测试。这些测试中的一些很容易成为<code>异步,它只提供<code>async 测试应用程序的一些关键方面如下: 这是一个巨大的ASP.NET应用程序(尽管代码在通过单元测试执行时没有在ASP.NET上下文中运行)。 在其核心中,它严重依赖于每个线程缓存上下文信息(例如活动用户的整个权限方案)的静态对象。 现在,我的问题是当在方法中使用时,延续可能发生在与以前不