Asynchronous code that works in Console but not in Windows Forms

后端 未结 2 478
萌比男神i
萌比男神i 2020-12-21 00:34

I am trying to write an application the is constantly searching for host on a lan. When I run this as a console as the countdown.Wait() seems to work fine. However when I

2条回答
  •  悲哀的现实
    2020-12-21 01:26

    Yes, your code deadlocks when you use it in a Winforms project. The problem is that the Ping class makes a best effort to raise the PingCompleted event on the same thread that called SendAsync(). It uses the AsyncOperationManager.CreateOperation() method to do so.

    Problem is, that actually works in a Winforms app. It tries to raise the event on the main thread. But that cannot work since you blocked the main thread with the countdown.Wait() call. The ping cannot complete since the main thread is blocked. The main thread cannot complete since the ping doesn't complete. Deadlock city.

    It works in a Console mode app since it doesn't have a synchronization provider like Winforms does. The PingComplete event will be raised on a threadpool thread.

    Blocking the UI thread is fundamentally flawed. The quick fix is to run the code on a worker thread. Beware that this makes the ProbeCompleted event fired on that worker as well. Use Control.BeginInvoke() to marshal it to the UI thread. Or use BackgroundWorker.

        private void Form1_Load(object sender, EventArgs e) {
            PortScanner ps = new PortScanner();
            ps.ProbeCompleted += new PingProbeCompleted(ps_ProbeCompleted);
            ThreadPool.QueueUserWorkItem((w) => ps.run_ping_probe());
        }
    

    And don't forget to remove the extra Signal() call.

提交回复
热议问题