使用Dispatcher.BeginInvoke()创建时,为什么消息框不能用作模态对话框?

时间:2017-07-06 16:27:40

标签: c# multithreading asynchronous modal-dialog dispatcher

我设法使用Task.Run()Dispatcher.BeginInvoke()的组合创建异步模式对话框。

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace WpfTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            var context = SynchronizationContext.Current;

            MessageBox.Show("Modal dialog on same thread. " + Thread.CurrentThread.ManagedThreadId);

            // Why do these two seem to behave the same despite Task.Run() using a different thread?
            Task.Run(() => MessageBox.Show("Attempted modal dialog on different thread using Task.Run(). " + Thread.CurrentThread.ManagedThreadId));
            Dispatcher.BeginInvoke(new Action(() => MessageBox.Show("Attempted asynchronous modal dialog on same thread using Dispatcher.BeginInvoke(). " + Thread.CurrentThread.ManagedThreadId)));

            // This behaves as desired.
            Task.Run(() => Dispatcher.BeginInvoke(new Action(() => MessageBox.Show("Attempted modal dialog from different thread using Task.Run() AND Dispatcher.BeginInvoke(). " + Thread.CurrentThread.ManagedThreadId))));

            // These are unreliable. They behave as desired when they're the only dialog shown.
            Task.Run(() => context.Send(state => MessageBox.Show("Attempted synchronous modal dialog on same thread using SynchronizationContext.Send(). " + Thread.CurrentThread.ManagedThreadId), null));
            Task.Run(() => context.Post(state => MessageBox.Show("Attempted asynchronous modal dialog on same thread using SynchronizationContext.Post(). " + Thread.CurrentThread.ManagedThreadId), null));
        }
    }
}

仅使用Task.Run()时,对话框不是模态的。也就是说,在对话框打开时,主窗口仍然可以获得焦点。仅使用Dispatcher.BeginInvoke()具有相同的行为。这是为什么?如果在主UI线程上创建对话框,为什么该对话框不是模态的?当它从另一个线程调用时,为什么它会正常工作?

此外,为什么SynchronizationContext.Post()与[{1}}的工作方式相同,只看Dispatcher.BeginInvoke()只调用DispatcherSynchronizationContext.Post()

http://referencesource.microsoft.com/#WindowsBase/Base/System/Windows/Threading/DispatcherSynchronizationContext.cs,b0fe97eb4a42faff

Dispatcher.BeginInvoke()

如果有人能够对此有所了解或指出我所遗漏的任何事情,我将不胜感激。如果您想知道,我需要异步创建模式对话框的原因是因为我需要不阻止UI线程,因为代码实际上是从 /// <summary> /// Asynchronously invoke the callback in the SynchronizationContext. /// </summary> public override void Post(SendOrPostCallback d, Object state) { // Call BeginInvoke with the cached priority. Note that BeginInvoke // preserves the behavior of passing exceptions to // Dispatcher.UnhandledException unlike InvokeAsync. This is // desireable because there is no way to await the call to Post, so // exceptions are hard to observe. _dispatcher.BeginInvoke(_priority, d, state); } 控件中运行的ActionScript调用的,它会抛出脚本超时错误,如果它认为它执行了很长时间。

0 个答案:

没有答案