新的 C# 等待功能有啥作用? [关闭]
Posted
技术标签:
【中文标题】新的 C# 等待功能有啥作用? [关闭]【英文标题】:What's the new C# await feature do? [closed]新的 C# 等待功能有什么作用? [关闭] 【发布时间】:2011-05-02 17:22:19 【问题描述】:谁能解释await
函数的作用?
【问题讨论】:
你指的是这个吗? Asynchronous Programming in C# 5.0 part two: Whence await? 另见Asynchronous Programming with Async and Await dotnetperls.com/async 也有很好的例子。 我不认为这个问题太宽泛或应该关闭。它询问一个关键字的含义。 (早期版本是否有所不同?) 【参考方案1】:对于不熟悉 .NET 中的异步编程的任何人,这里有一个(完全是假的)类比,在您可能更熟悉的场景中 - 使用 javascript/jQuery 的 AJAX 调用。一个简单的 jQuery AJAX 帖子如下所示:
$.post(url, values, function(data)
// AJAX call completed, do something with returned data here
);
我们在回调函数中处理结果的原因是我们在等待 AJAX 调用返回时不会阻塞当前线程。只有当响应准备好时,回调才会被触发,同时释放当前线程来做其他事情。
现在,如果 JavaScript 支持 await
关键字(当然不支持 (yet!)),您可以通过以下方式实现相同的效果:
var data = await $.post(url, values);
// AJAX call completed, do something with returned data here
这样更简洁,但看起来我们确实引入了同步阻塞代码。但是(假的)JavaScript 编译器会获取 await
之后的所有内容并将其连接到回调中,因此在运行时第二个示例的行为与第一个示例一样。
它可能看起来并没有为您节省很多工作,但是当涉及到异常处理和同步上下文等事情时,编译器实际上为您做了很多大量繁重的工作。更多信息,我推荐FAQs,然后是Stephen Cleary's blog series。
【讨论】:
坚持这个虚假的类比(顺便说一句,这对我帮助很大,所以谢谢!),“之后的一切”是什么意思?一切都只属于同一个函数(方法)吗?或者它之后的所有内容都可以添加到调用堆栈中? "Everything after" = 方法的其余部分。编译器有效地将方法的其余部分重写为回调,并且控制立即返回给当前方法的调用者。 杰出的托德,再次感谢您的解释。我相信对其他人也有用。【参考方案2】:如果我必须在 Java 中实现它,它会看起来像这样:
/**
* @author Ilya Gazman
*/
public abstract class SynchronizedTask
private ArrayList<Runnable> listeners = new ArrayList<Runnable>();
private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(6, 6, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1000));
public final void await(Runnable listener)
synchronized (this)
listeners.add(listener);
public void excecute()
onExcecute();
for (int i = listeners.size() - 1; i >= 0; i--)
Runnable runnable;
synchronized (this)
runnable = listeners.remove(i);
threadPoolExecutor.execute(runnable);
protected abstract void onExcecute();
您的应用程序会这样使用它:
public class Test
private Job job = new Job();
public Test()
craeteSomeJobToRunInBackground();
methode1();
methode2();
private void methode1()
System.out.println("Running methode 1");
job.await(new Runnable()
@Override
public void run()
System.out.println("Continue to running methode 1");
);
private void methode2()
System.out.println("Running methode 2");
private void craeteSomeJobToRunInBackground()
new Thread(new Runnable()
@Override
public void run()
job.excecute();
).start();
private class Job extends SynchronizedTask
@Override
protected void onExcecute()
try
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
System.out.println("Job is done");
【讨论】:
【参考方案3】:当前接受的答案具有误导性。
await
没有暂停任何内容。
首先,它只能在标记为 async
的方法或 lambdas 中使用,如果您不关心在此方法中运行 Task
实例,则返回 Task
或 void
。
这是一个插图:
internal class Program
private static void Main(string[] args)
var task = DoWork();
Console.WriteLine("Task status: " + task.Status);
Console.WriteLine("Waiting for ENTER");
Console.ReadLine();
private static async Task DoWork()
Console.WriteLine("Entered DoWork(). Sleeping 3");
// imitating time consuming code
// in a real-world app this should be inside task,
// so method returns fast
Thread.Sleep(3000);
await Task.Run(() =>
for (int i = 0; i < 10; i++)
Console.WriteLine("async task iteration " + i);
// imitating time consuming code
Thread.Sleep(1000);
);
Console.WriteLine("Exiting DoWork()");
输出:
进入 DoWork()。睡觉 3 异步任务迭代 0 任务状态:WaitingForActivation 等待 ENTER 异步任务迭代 1 异步任务迭代 2 异步任务迭代 3 异步任务迭代 4 异步任务迭代 5 异步任务迭代 6 异步任务迭代 7 异步任务迭代 8 异步任务迭代 9 退出 DoWork()
【讨论】:
你也知道它会阻止调用者 3 秒钟,然后才会给他们他们可以await
执行的任务?这意味着如果从 UI 线程调用它会阻塞 UI 线程 3 秒?这个模型的想法是避免做这样的事情。
@Servy 是的,这就是重点。显示执行的所有阶段。这不是一个真实的例子。
@Servy 你在骗我吗?
不。我正在努力帮助您改进答案。
@Anri ...我非常感谢您在这里所做的努力。非常感谢!!【参考方案4】:
他们昨天刚刚talked about this at PDC!
Await 与 .NET 中的任务(并行编程)结合使用。它是 .NET 下一版本中引入的关键字。它或多或少让您“暂停”方法的执行以等待 Task 完成执行。这是一个简短的例子:
//create and run a new task
Task<DataTable> dataTask = new Task<DataTable>(SomeCrazyDatabaseOperation);
//run some other code immediately after this task is started and running
ShowLoaderControl();
StartStoryboard();
//this will actually "pause" the code execution until the task completes. It doesn't lock the thread, but rather waits for the result, similar to an async callback
// please so also note, that the task needs to be started before it can be awaited. Otherwise it will never return
dataTask.Start();
DataTable table = await dataTask;
//Now we can perform operations on the Task result, as if we're executing code after the async operation completed
listBoxControl.DataContext = table;
StopStoryboard();
HideLoaderControl();
【讨论】:
什么时候是C#形式的promise:en.wikipedia.org/wiki/Futures_and_promises 听起来很像 Thread.Join()。 让我想起了COMEFROM 为了完整起见,让我们补充一点,上面的代码必须包装在一个带有 async 关键字的方法中。一旦在其中遇到第一个 await 关键字,此方法将立即返回。 用你的话说:它可以让你“暂停”方法,但需要注意的是它不会暂停或阻塞线程。【参考方案5】:基本上,async
和 await
关键字允许您指定方法的执行应在所有使用标记异步方法调用的await
时停止,然后在异步操作完成后恢复。这允许您在应用程序的主线程中调用方法并异步处理复杂的工作,而无需显式定义线程和连接或阻塞应用程序的主线程。
认为它有点类似于生成 IEnumerable 的方法中的 yield return
语句。当运行时到达yield
时,它基本上会保存方法的当前状态,并返回正在产生的值或引用。下次在返回对象(由运行时内部生成)上调用 IEnumerator.MoveNext() 时,方法的旧状态将恢复到堆栈中,并继续执行 yield return
之后的下一行,就像我们要从未离开过方法。如果没有此关键字,则必须自定义 IEnumerator 类型来存储状态和处理迭代请求,其方法确实会变得非常复杂。
同样,标记为async
的方法必须至少有一个await
。在await
上,运行时将保存当前线程的状态和调用堆栈,进行异步调用,然后回到运行时的消息循环以处理下一条消息并保持应用程序响应。当异步操作完成时,在下一个调度机会时,向上异步操作的调用堆栈被推回并继续,就像调用是同步的一样。
所以,这两个新关键字基本上简化了异步进程的编码,很像yield return
简化了自定义枚举的生成。使用几个关键字和一点背景知识,您可以跳过传统异步模式中所有令人困惑且经常出错的细节。这在几乎任何事件驱动的 GUI 应用程序(如 Winforms、Silverlight 的 WPF)中都是无价的。
【讨论】:
以上是关于新的 C# 等待功能有啥作用? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
c#开发winform程序,如何做等待窗体?等待窗体上面只有个一gif图片和文字,读取完成后等待窗体关闭。
C# Discord如何等待带有前缀的消息,然后响应它[关闭]