2017-07-19 182 views
0

我正在使用我在網上找到的用戶控件來表示處理。子窗口阻塞主線程

我想要做的是顯示一個包含此用戶控件的窗口,直到主線程完成處理。

這是用戶控制代碼:

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(); 
} 

這是阻止主線程的執行,我不知道我做了什麼錯誤,因爲我是新手。

回答

1

Dispatcher.Run肯定是阻塞的。您不能在主線程上調用此方法而不會阻塞。

如果你想在一個專用的線程出於某種原因創建一個新的窗口,你可以參考@Reed科普塞的博客文章:

在一個單獨的線程啓動一個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(); 
+0

感謝,在這種情況下,我將如何能夠從主線程關閉它? –

+0

使用窗口的調度程序。但如果您有其他問題,請提出一個新問題。 – mm8