gpt4 book ai didi

c# - 在单独线程中加载屏幕的问题

转载 作者:太空狗 更新时间:2023-10-29 23:38:03 24 4
gpt4 key购买 nike

我在 Windows 窗体中有一个旧应用程序,它在许多地方对数据库进行一些搜索。有时这会花费很多时间,所以我决定在 wpf 中创建一个加载屏幕,以向用户显示某些内容正在单独的线程中加载。基本上它只是一个带有加载指示器(转圈)的全透明窗口。在我的主机和我的虚拟机上一切正常,但是当我尝试将它部署到我们的演示环境时它就像 - 它开始加载指示器显示,几秒钟后它消失并且应用程序永远停止响应。我的第一个想法是这是 GPU 加速的问题,它无法处理透明度,但它会显示几秒钟,所以这不是问题所在。所以很可能我做了坏事。下面您可以看到我的代码,您是否注意到可能有问题/导致死锁或其他问题?

  public class LoadingManager
{
public LoadingManager()
{ }
public LoadingManager(string LoadingText)
{
loadingText = LoadingText;
}

private string loadingText = "Please wait ..";
private Thread thread;
private bool ThreadReadyToAbort = false;
private BusyIndicatorView loadingWindow;

public void BeginLoading()
{
this.thread = new Thread(this.RunThread);
this.thread.IsBackground = true;
this.thread.SetApartmentState(ApartmentState.STA);
this.thread.Start();
}

public void EndLoading()
{
if (this.loadingWindow != null)
{
this.loadingWindow.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
{ this.loadingWindow.Close(); }));
while (!this.ThreadReadyToAbort) { }; // I also tried to remove this while but it didn't help
}
this.thread.Abort();
}

public void RunThread()
{
this.loadingWindow = new BusyIndicatorView();

loadingWindow.tbLoadingCaption.Text = loadingText;
this.loadingWindow.Closing += new System.ComponentModel.CancelEventHandler(waitingWindow_Closed);
this.loadingWindow.ShowDialog();
}

void waitingWindow_Closed(object sender, System.ComponentModel.CancelEventArgs e)
{
Dispatcher.CurrentDispatcher.InvokeShutdown();
this.ThreadReadyToAbort = true;
}

编辑。

我注意到在这台机器上,当我第一次点击搜索时,它通常(有时它在第一次点击时也会失败)工作。如果我再次单击它会显示一秒钟而不是消失并且应用程序停止响应。所以看起来 Thread 没有关闭,Dispatcher 关闭失败?但是没有抛出异常......

最佳答案

您的 BeginLoading 方法在完成之前可以被多次调用,因此可以创建多个 wpf 窗口。这搞乱了各种引用资料。也不要中止线程,让它自己决定。以下是两个更改:

public void BeginLoading()
{
this.thread = new Thread(this.RunThread);
this.thread.IsBackground = true;
this.thread.SetApartmentState(ApartmentState.STA);
this.thread.Start();
while (this.loadingWindow == null) { } // <--- Add this line
}

public void EndLoading()
{
if (this.loadingWindow != null)
{
this.loadingWindow.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
{ this.loadingWindow.Close(); }));
while (!this.ThreadReadyToAbort) { };
}
//this.thread.Abort(); // <-- Remove this line
}

此外,如果这只是为了繁忙的屏幕,我会说必须有比这更好、更安全的方法。出于学术目的,这是一个有趣的问题,但不是生产代码,特别是如果一些初级开发人员将来可能会摆弄这个问题。

编辑:如果我减少重复调用 BeginLoading 和 EndLoading 之间的延迟,我的机器仍然会崩溃。可能与wpf窗口如何异步关闭有关。我删除了 Closed 事件处理程序,只使用了一个 bool 标志来指示窗口是否“已加载”,我没有看到任何问题:

public class LoadingManager2
{
public LoadingManager2()
{ }
public LoadingManager2(string LoadingText)
{
loadingText = LoadingText;
}

private string loadingText = "Please wait ..";
private Thread thread;
private MyWindow loadingWindow;
private bool isLoaded = false;

public void BeginLoading()
{
this.thread = new Thread(this.RunThread);
this.thread.IsBackground = true;
this.thread.SetApartmentState(ApartmentState.STA);
this.thread.Start();
while (!this.isLoaded) { };
}

public void RunThread()
{
this.loadingWindow = new MyWindow();
this.isLoaded = true;
this.loadingWindow.ShowDialog();
}

public void EndLoading()
{
this.loadingWindow.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
{
this.loadingWindow.Close();
this.isLoaded = false;
}));
while (this.isLoaded) { };
}
}

关于c# - 在单独线程中加载屏幕的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31624396/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com