c#在新线程中启动子WPF
本文关键字:启动 WPF 线程 新线程 | 更新日期: 2023-09-27 18:12:47
我正在寻找以下问题的帮助,我正在经历。
我已经花了两天时间在这个网站和谷歌上搜索,尝试了很多不同的方法来解决我的问题,到目前为止我还没有运气。我知道我还没有足够的阅读多线程,这将是我学习旅程中的下一个待办事项。我对c#相当陌生,所以请温柔一点。
我的主WPF应用程序有一个按钮,我已经标记为"INFO"。在"INFO"按钮的CLICK事件上,我需要启动一个单独的WPF,它只包含WEBBROWSER对象。我在web浏览器对象中显示我们的内部网站点。
我需要能够完成以下任务:
- 我需要在自己的THREAD中启动WPF浏览器,以便即使启动了对话框,WPF也完全可用。
- 然后,我需要能够确保WPF在自己的线程中被重新激活,当用户点击INFO按钮时,如果线程已经在运行。
- 当主WPF关闭时,我需要确保所有打开的线程也被关闭。
我在寻找最简单的解决方案。
我在地方的样例代码
//在公共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);
}
}
给你:
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));
}
}
使用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);
}
}
}
浏览器窗口添加此属性:=>
public MainWindow WinOwner
{
get { return _winOwner; }
set
{
_winOwner = value;
if (value is IWinOwnerCollection)
{
((IWinOwnerCollection)value).WinOwnerCollection.Add(this);
}
}
}