在wpf的线程中打开的窗口有多近
本文关键字:窗口 wpf 线程 | 更新日期: 2023-09-27 18:00:40
根据规范,我构建了一个监视特定资源的应用程序。现在我有一个主窗口,当事件发生时,它会发出警报,说明必须是一个颜色明亮的大窗口。我给出了问题的解决方案如下
private void StatusChanges(Alarm m, EventArgs e)
{
//Compares two 32-bit signed integers for equality and, if they are equal, replaces one of the values.
if (Interlocked.CompareExchange(ref running, 1, 0) == 0)
{
newWindowThread = new Thread(new ThreadStart(() =>
{
try
{
// Create and show the Window
Alert tempWindow = new Alert();
tempWindow.Show();
//if (cancelRun)
// tempWindow.Close();
// Start the Dispatcher Processing
System.Windows.Threading.Dispatcher.Run();
}
catch (Exception)
{
throw;
}
finally
{
running = 0;
}
}));
// Set the apartment state
newWindowThread.SetApartmentState(ApartmentState.STA);
// Make the thread a background thread
newWindowThread.IsBackground = true;
newWindowThread.Start();
}
}
else
{
if (Interlocked.CompareExchange(ref running, 0, 1) == 1)
{
try
{
System.Windows.Threading.Dispatcher.FromThread(newWindowThread).InvokeShutdown();
Alert tempWindow = new Alert();
tempWindow.Close();
}
catch (Exception)
{
//throw;
MessageBox.Show("Todo esta ok");
}
}
//running = 0;
}
}
此方法由定时每隔一段时间执行一次
我的目标是当警报将结束删除警报窗口的过程时,我使用Thread.Artrt();不起作用,有时程序会抛出一个异常,显示外面没有视觉工作室,尝试使用threa.Join ();
,但没有起作用,直到
System.Windows.Threading.Dispatcher.FromThread use (newWindowThread) InvokeShutdown ().;
这至少停止了窗口的显示,但当我创建时
Alert tempWindow = new Alert();
在初始化构造函数中
SoundPlayer player = new Sound ("../../Sounds/BOMB_SIREN-BOMB_SIREN-247265934.wav");
player.PlayLooping();
当我关闭窗口时
player.Stop();
现在,如果不是,但我做下一个
Alert tempWindow = new Alert();
tempWindow.Close();
声音继续播放
我知道这不是最好的解决方案,但它有效。我想给我你的意见,并给我如何改进代码的建议。
快速查看您的代码,您所做的是错误地关闭临时窗口。当您想要关闭现有窗口时,您正在创建一个全新的窗口。这应该更新,以便保存现有的临时窗口,以便以后可以关闭相同的实例。
我还更新了临时窗口的关闭,这样它就可以在关闭后关闭线程。
我更新代码如下:
Alert _tempWindow;
private void StatusChanges(Alarm m, EventArgs e)
{
//Compares two 32-bit signed integers for equality and, if they are equal, replaces one of the values.
if (Interlocked.CompareExchange(ref running, 1, 0) == 0)
{
newWindowThread = new Thread(new ThreadStart(() =>
{
try
{
// Create and show the Window
_tempWindow = new Alert();
_tempWindow.Close += OnTempClosed;
_tempWindow.Show();
System.Windows.Threading.Dispatcher.Run();
}
catch (Exception)
{
throw;
}
finally
{
running = 0;
}
}));
// Set the apartment state
newWindowThread.SetApartmentState(ApartmentState.STA);
// Make the thread a background thread
newWindowThread.IsBackground = true;
newWindowThread.Start();
}
}
else
{
if (Interlocked.CompareExchange(ref running, 0, 1) == 1)
{
try
{
_tempWindow.Dispatcher.BeginInvoke((Action)_tempWindow.Close);
}
catch (Exception)
{
//throw;
MessageBox.Show("Todo esta ok");
}
}
//running = 0;
}
}
private void OnTempClosed(object sender, EventArgs e)
{
System.Windows.Threading.Dispatcher.FromThread(newWindowThread).InvokeShutdown();
}
我们的想法是只从一个线程处理UI。因此,与其创建一个全新的调度器,为什么不简单地将新的窗口逻辑调度到现有的UI线程上呢(毕竟,计时器不是已经自己在UI线程上结束了吗?)。
为什么要在新线程中启动新窗口?你希望通过这种方式实现什么?
你的关闭代码没有意义:
Dispatcher.FromThread(newWindowThread).InvokeShutdown();
Alert tempWindow = new Alert();
tempWindow.Close();
让我们走过来。首先,关闭第二个UI线程的调度器。这意味着所有会流到窗口的消息都不会。
然后,在原始UI线程上创建一个新窗口,然后关闭它。这应该实现什么?您要关闭以前打开的窗口,而不是新窗口!
在实践中,你需要保留对你打开的原始窗口的引用——对它的线程的引用并不重要。现在,如果你真的想继续使用两个UI线程的方法,你可以这样做:
alertWindow.Dispatcher.Invoke(alertWindow.Close);
这将告诉(已打开的)警报窗口上的消息循环尽快关闭该窗口。
这样一来,您的代码就会出现太多错误。首先,您使用的操作级别太低(Interlocked.CompareExchange
用于维护警报/无警报逻辑?)。第二,你的评论完全没有用——你只是在说下一行的作用——这没有帮助。代替
// Compares two 32-bit signed integers for equality and,
// if they are equal, replaces one of the values.
你想用一些描述你试图实现的目标的东西,而不是你是如何实现的:
// If we're the first ones to attempt to change the running flag,
// we'll create a new alert window.
请注意,这条评论也很好地表明你在做一些非常奇怪的事情。
第三,您不必要地创建线程(UI线程更是如此——除了非常特殊的情况外,实际上应该只有一个)。没有任何理由在新线程中创建新窗口。你为什么这么做?
第四,您的异常处理也没有多大帮助。首先,如果您所做的只是重新引发异常,那么您可以省略catch
子句——您可以只使用try ... finally
。更重要的是,异常将传播到新线程,而不是旧线程——这很可能会导致应用程序完全崩溃。