C#在新线程

时间:2015-09-15 18:12:00

标签: c# wpf multithreading

我正在寻找我遇到的以下问题的帮助。

我花了两天时间通过这个网站搜索并通过谷歌 - 尝试了许多不同的事情来解决我的问题,到目前为止我没有运气。我知道我还没有对多线程做足够的阅读,这将是我学习之旅中的下一个待办事项。我是C#的新手,所以请保持温和。

我的主要WPF应用程序有一个按钮,我将其标记为“INFO”。在“INFO”按钮的CLICK事件中,我需要启动一个单独的WPF,它只包含WEBBROWSER对象。我在webbrowser对象中显示我们的Intranet站点。

我需要能够完成以下任务:

  1. 我需要在自己的THREAD中启动WPFBrowser,以便即使启动了一个对话框,WPF也可以完全可用。
  2. 然后我需要能够确保当用户点击INFO按钮时,如果线程已经在运行,则自动线程中的WPF将被重新激活。
  3. 当主WPF关闭时,我还需要确保所有打开的线程都关闭。
  4. 我正在寻找最简单的解决方案。

    我所拥有的示例代码

    //这是在公共MainWindow()上面声明的     线程newWindowThread;

    private async void btn_LaunchWPFBrowser_Click(object sender, RoutedEventArgs e)
          {
                try
                {
                        if (newWindowThread == null)
                        {
                            newWindowThread = new Thread(() =>
                            {
                                var wpfwindow = new WPF_Windows.wpf_Browser();
                                wpfwindow.Show();
    
                                wpfwindow.Closed += (sender2, e2) => wpfwindow.Dispatcher.InvokeShutdown();
    
                                // Start the Dispatcher Processing
                                System.Windows.Threading.Dispatcher.Run();
                            });
    
                            // Set the apartment state
                            newWindowThread.SetApartmentState(ApartmentState.STA);  //setting new thread’s apartment state to STA, this is a WPF requirement
                            newWindowThread.Start();
                        }
                        else if (newWindowThread.ThreadState == ThreadState.Running)
                        {
                            //wpfwindow.Activate();
    
                        }
                }
                catch (Exception ex)
                {
                    string additionalMessage = "In method '" + TraceCallerClass.TraceCaller() + "' ";
    
                    MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
    
                }
            }
    

2 个答案:

答案 0 :(得分:0)

你走了:

private object syncGate = new object();
private Thread browserWindowThread;
private Window browserWindow;

private void btn_LaunchWPFBrowser_Click(object sender, RoutedEventArgs e)
{
    try
    {
        lock (syncGate)
        {
            if (browserWindowThread == null)
            {
                browserWindowThread = new Thread(() =>
                {
                    var wpfwindow = new WPF_Windows.wpf_Browser();
                    wpfwindow.Show();
                    wpfwindow.Closed += (sender2, e2) => wpfwindow.Dispatcher.InvokeShutdown();
                    lock (syncGate)
                        browserWindow = wpfwindow;
                    // Start the Dispatcher Processing
                    System.Windows.Threading.Dispatcher.Run();
                    lock (syncGate)
                    {
                        browserWindow = null;
                        browserWindowThread = null;
                    }
                });
                browserWindowThread.IsBackground = true;
                // Set the apartment state
                browserWindowThread.SetApartmentState(ApartmentState.STA);  //setting new thread’s apartment state to STA, this is a WPF requirement
                browserWindowThread.Start();
            }
            else if (browserWindow != null)
            {
                browserWindow.Dispatcher.BeginInvoke(new Func<bool>(browserWindow.Activate));
            }
        }
    }
    catch (Exception ex)
    {
        string additionalMessage = "In method '" + TraceCallerClass.TraceCaller() + "' ";

        MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

protected override void OnClosed(EventArgs e)
{
    base.OnClosed(e);
    lock (syncGate)
    {
        if (browserWindow != null)
            browserWindow.Dispatcher.BeginInvoke(new Action(browserWindow.Close));
    }
}

答案 1 :(得分:0)

使用Task而不是Thread来轻松关闭进程。 我的提议使用这种方式...

public interface IWinOwnerCollection
    {
        List<Window> WinOwnerCollection { get; }
    }

class MainWindow : Window, IWinOwnerCollection
    {
        public List<Window> WinOwnerCollection { get; private set; }

        Task newWindowTask;

        public MainWindow()
        {
            InitializeComponent();
            WinOwnerCollection = new List<Window>();
            this.Closed += (sender, args) =>
            {
                newWindowTask = null;
            };
        }

        private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            try
            {

                if (newWindowTask == null)
                {
                    newWindowTask = new Task(() =>
                    {
                        Dispatcher.Invoke(() =>
                        {
                            var wpfwindow = new Window1();
                            wpfwindow.WinOwner = this;
                            wpfwindow.Show();

                            wpfwindow.WinOwner.Closed += (o, args) =>
                            {
                                wpfwindow.Close();
                                //newWindowTask.Abort();
                            };
                        }, DispatcherPriority.Render);
                    });
                    newWindowTask.Start();
                }
                else if (newWindowTask.Status == TaskStatus.RanToCompletion)
                {
                    foreach (var window in WinOwnerCollection)
                    {
                        window.Activate();
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }


    }

浏览器窗口添加此属性:=&gt;

public MainWindow WinOwner
        {
            get { return _winOwner; }
            set
            {
                _winOwner = value;
                if (value is IWinOwnerCollection)
                {
                    ((IWinOwnerCollection)value).WinOwnerCollection.Add(this);
                }
            }
        }