async方法阻止它正在执行的UI线程

时间:2014-08-13 20:06:27

标签: c# async-await

在Winform中考虑以下代码。当我单击该按钮时,我希望async方法不应该阻止它正在执行的UI线程。

然而,我发现在异步方法调用期间该按钮被冻结了...... 如果是,那么异步方法有什么意义呢?我很困惑。

namespace WindowsFrmAsyn
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        async private void button1_Click(object sender, EventArgs e)
        {
            int contentlength = await AccessTheWebAsync();
            tbResult.Text =
                        string.Format("Length of the downloaded string: {0}.", contentlength);

            Debug.WriteLine(tbResult.Text);
        }    

        async Task<int> AccessTheWebAsync()
        {
            Debug.WriteLine("Call AccessTheWebAsync");
            Thread.Sleep(5000);
            Debug.WriteLine("Call AccessTheWebAsync done");
            tbResult.Text = "I am in AccessTheWebAsync";
            return 1000;
        }
    }
}

3 个答案:

答案 0 :(得分:6)

编译器警告确切地告诉您发生了什么:由于您的async方法不会await,它将同步运行。

Thread.Sleep是同步操作;如果要伪造异步操作,请使用Task.Delay

async Task<int> AccessTheWebAsync()
{
  Debug.WriteLine("Call AccessTheWebAsync");
  await Task.Delay(5000);
  Debug.WriteLine("Call AccessTheWebAsync done");
  tbResult.Text = "I am in AccessTheWebAsync";
  return 1000;
}

答案 1 :(得分:1)

目前您在AccessTheWebAsync中缺乏等待,因为您没有等待任何事情,因此所有代码都在主线程上运行。 Async / await不会使该方法在除您等待的部分之外的其他线程上运行。

方法必须是这样的。

async Task<int> AccessTheWebAsync()
{
     // Console writeline
     await Task.Delay(seconds);
     // Console WriteLine.
     return value;
}

因此,异步方法中await之前和之后的所有内容都在调用该方法的同一个线程上运行。 (可选)您可以使用库中常用的ConfigureAwait,以便await之后的所有内容都在await已经完成的同一个线程中发生。

结帐http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/async-await-faq.aspx以获取有关async / await的更多信息。

答案 2 :(得分:0)

编写此类代码时:

 SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
 SLF4J: Defaulting to no-operation (NOP) logger implementation
 SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further  details.
 Exception in thread "JavaFX Application Thread" java.lang.RuntimeException:     java.lang.reflect.InvocationTargetException
 at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
 at  javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
 at  com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventH andler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at  com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManag er.java:191)
at  com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at  com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at  com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at  com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at  com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at  com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at  com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl .java:114)
  at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
  at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
  at javafx.event.Event.fireEvent(Event.java:198)
  at javafx.scene.Node.fireEvent(Node.java:8413)
  at javafx.scene.control.Button.fire(Button.java:185)
  at  com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
 at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
 at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
 at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
 at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
 at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
 at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
 at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
 at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
 at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
 at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
 at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
 at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
 at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
 at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
 at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
 at javafx.event.Event.fireEvent(Event.java:198)
 at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
 at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
 at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
 at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
 at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
 at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
 at java.security.AccessController.doPrivileged(Native Method)
 at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:417)
 at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
 at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
 at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
 at com.sun.glass.ui.View.notifyMouse(View.java:937)
 at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
 at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
 at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetException
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
 at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
 at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771)
 ... 48 more
 Caused by: quickfix.ConfigError: no initiators in settings
at quickfix.mina.initiator.AbstractSocketInitiator.createSessions(AbstractSocketInitiator.java:202)
  at quickfix.mina.initiator.AbstractSocketInitiator.createSessionInitiators(AbstractSocketInitiator.java:83)
  at quickfix.SocketInitiator.initialize(SocketInitiator.java:114)
  at quickfix.SocketInitiator.start(SocketInitiator.java:89)
  at controller.Controller.connectButtonAction(Controller.java:174)
     ... 58 more

这样你就可以同步处理,因为你没有使用等待表达式。

注意警告:

private async Task<int> DoStuffAsync()
{
    return 0;
}

根据警告建议,您可以这样纠正:

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.