【问题标题】:Child window is blocking the main thread子窗口阻塞了主线程
【发布时间】:2017-12-24 14:07:22
【问题描述】:

我正在使用我在网上找到的用户控件来表达处理。

我要做的是在主线程完成处理之前显示一个包含此用户控件的窗口。

这是用户控制代码:

public partial class CircularProgressBar
{
    #region Data

    private readonly DispatcherTimer animationTimer;

    #endregion

    #region Constructor

    public CircularProgressBar()
    {
        InitializeComponent();

        animationTimer = new DispatcherTimer( DispatcherPriority.ContextIdle, Dispatcher);
        animationTimer.Interval = new TimeSpan(0, 0, 0, 0, 75);
    }

    #endregion

    #region Private Methods

    private void Start()
    {
        Mouse.OverrideCursor = Cursors.Wait;
        animationTimer.Tick += HandleAnimationTick;
        animationTimer.Start();
    }

    private void Stop()
    {
        animationTimer.Stop();
        Mouse.OverrideCursor = Cursors.Arrow;
        animationTimer.Tick -= HandleAnimationTick;
    }

    private void HandleAnimationTick(object sender, EventArgs e)
    {
        SpinnerRotate.Angle = (SpinnerRotate.Angle + 36) % 360;
    }

    private void HandleLoaded(object sender, RoutedEventArgs e)
    {
        const double offset = Math.PI;
        const double step = Math.PI * 2 / 10.0;

        SetPosition(C0, offset, 0.0, step);
        SetPosition(C1, offset, 1.0, step);
        SetPosition(C2, offset, 2.0, step);
        SetPosition(C3, offset, 3.0, step);
        SetPosition(C4, offset, 4.0, step);
        SetPosition(C5, offset, 5.0, step);
        SetPosition(C6, offset, 6.0, step);
        SetPosition(C7, offset, 7.0, step);
        SetPosition(C8, offset, 8.0, step);
    }

    private void SetPosition(Ellipse ellipse, double offset, double posOffSet, double step)
    {
        ellipse.SetValue(Canvas.LeftProperty, 50.0 + Math.Sin(offset + posOffSet * step) * 50.0);
        ellipse.SetValue(Canvas.TopProperty, 50 + Math.Cos(offset + posOffSet * step) * 50.0);
    }

    private void HandleUnloaded(object sender, RoutedEventArgs e)
    {
        Stop();
    }

    private void HandleVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        bool isVisible = (bool)e.NewValue;

        if (isVisible)
            Start();
        else
            Stop();
    }

    #endregion
}

XAML:

<UserControl Height="Auto" Width="Auto" Background="Transparent" IsVisibleChanged="HandleVisibleChanged">
    <Grid x:Name="LayoutRoot" Background="Transparent" ToolTip="Searching...."  HorizontalAlignment="Center" VerticalAlignment="Center">
        <Canvas RenderTransformOrigin="0.5,0.5"
                HorizontalAlignment="Center"
             VerticalAlignment="Center" Width="120"
             Height="120" Loaded="HandleLoaded"
                Unloaded="HandleUnloaded"  >
            <Ellipse x:Name="C0" Width="20" Height="20" Canvas.Left="0" Canvas.Top="0" Stretch="Fill" Fill="Black" Opacity="1.0"/>
            <Ellipse x:Name="C1" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.9"/>
            <Ellipse x:Name="C2" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.8"/>
            <Ellipse x:Name="C3" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.7"/>
            <Ellipse x:Name="C4" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.6"/>
            <Ellipse x:Name="C5" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.5"/>
            <Ellipse x:Name="C6" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.4"/>
            <Ellipse x:Name="C7" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.3"/>
            <Ellipse x:Name="C8" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.2"/>
            <Canvas.RenderTransform>
                <RotateTransform x:Name="SpinnerRotate"
                     Angle="0" />
            </Canvas.RenderTransform>
        </Canvas>
    </Grid>
</UserControl>

我在一个窗口中使用这个用户控件并在我开始处理时调用这个窗口:

private void ThreadStartingPoint()
{
    Window.Show();
    Window.Focus();
    System.Windows.Threading.Dispatcher.Run();
}

这阻塞了主线程的执行,我不知道我做错了什么,因为我是新手。

【问题讨论】:

    标签: c# wpf windows multithreading


    【解决方案1】:

    Dispatcher.Run 肯定会阻塞。你不能在不阻塞的情况下在主线程上调用这个方法。

    如果你出于某种原因想在专用线程上创建一个新窗口,你可以参考@Reed Copsey 的博文:

    在单独的线程中启动 WPF 窗口,第 1 部分: http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-a-separate-thread-part-1/

    它解释了如何正确地做到这一点:

    // Create a thread
    Thread newWindowThread = new Thread(new ThreadStart(() =>
    {
        // Create our context, and install it:
        SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher));
    
        Window1 tempWindow = new Window1();
        tempWindow.Content = new CircularProgressBar();
        // When the window closes, shut down the dispatcher
        tempWindow.Closed += (s, e) =>
        Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
    
        tempWindow.Show();
        // Start the Dispatcher Processing
        System.Windows.Threading.Dispatcher.Run();
    }));
    // Set the apartment state
    newWindowThread.SetApartmentState(ApartmentState.STA);
    // Make the thread a background thread
    newWindowThread.IsBackground = true;
    // Start the thread
    newWindowThread.Start();
    

    【讨论】:

    • 谢谢,在这种情况下,我怎样才能从主线程中关闭它?
    • 使用窗口的调度器。但是,如果您有其他问题,请提出一个新问题。
    猜你喜欢
    • 2019-09-01
    • 2011-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-01
    • 2020-01-02
    • 2018-03-03
    • 2018-02-16
    相关资源
    最近更新 更多