我有一个闪屏:
public partial class LoadingScreen : Form
{
private delegate void CloseDelegate();
private static LoadingScreen loadingscreen;
private LoadingScreen()
{
InitializeComponent();
}
private static void ShowForm()
{
loadingscreen = new LoadingScreen();
Application.Run(loadingscreen);
}
public static void ShowLoadingscreen()
{
if (loadingscreen != null)
return;
System.Threading.Thread thread = new System.Threading.Thread(LoadingScreen.ShowForm);
thread.IsBackground = true;
thread.SetApartmentState(System.Threading.ApartmentState.STA);
thread.Start();
}
public static void CloseForm()
{
loadingscreen.Invoke(new CloseDelegate(LoadingScreen.CloseFormInternal));
}
private static void CloseFormInternal()
{
loadingscreen.Close();
loadingscreen = null;
}
}
当数据网格忙于刷新(它需要一些绘图并且需要一段时间来处理我们的数据)时,用户也会使用文本框来搜索触发的内容,因为我们需要重新绘制所有内容。触发启动画面的代码:
private void EditGrid()
{
LoadingScreen.ShowLoadingscreen();
CheckItems();
EditGridVisibility();
LoadingScreen.CloseForm();
}
当用户在搜索框中键入3个,4个或5个字符时,我在LoadingScreen.CloseForm();
上收到NullReferenceException
这是正确的我得到一个NullRef,因为我没有看到调试中的形式,所以在显示(或关闭最后一次)时出现了问题,但我不明白为什么。
答案 0 :(得分:2)
在ShowLoadingScreen有时间旋转它的线程并创建loadingScreen之前调用CloseForm时会发生此错误。
在后台线程上加载/处理数据并在主UI线程上显示对话框几乎总是更容易。但如果无法做到这一点,请确保在取消对话框或中止其创建之前显示对话框。
一个粗略的解决方案是使线程全局化......
public static void CloseForm()
{
if (loadingscreen == null)
{
_thread.Abort();
return;
}
loadingscreen.Invoke(new CloseDelegate(CloseFormInternal));
}
答案 1 :(得分:0)
我使用过John的解决方案,并且在大多数情况下都能正常工作。但是,在某些情况下,_thread.Abort()
调用会导致应用程序崩溃,没有任何例外。查找起来,使用Thread.Abort()
似乎是非常糟糕的做法,就像杀死一个帖子一样(请参阅this,this,this,this和许多其他在线),正如其他人所说,不要使用Thread.Abort()!
这是一个完美运作的解决方案:
public static void CloseForm()
{
// Loop for a maximum of 100ms if the screen hasn't yet been loaded.
for (var i = 0; i < 100; i++)
{
if (loadingScreenForm != null && loadingScreenForm.IsHandleCreated)
{
break;
}
Thread.Sleep(1);
}
// Don't try to close if it is already closed.
// If the screen form is still null after waiting, it was most likely already closed.
if (loadingScreenForm != null && loadingScreenForm.IsHandleCreated)
{
loadingScreenForm.Invoke(new CloseDelegate(CloseFormInternal));
}
}
我的代码的细节要求我检查是否已创建句柄,但您可能没有它。在我们的情况发生的情况下,这将为代码增加100ms的开销。如果你觉得十分之一秒太多,你可以调整它。
我知道现在已经很晚了,但希望它能帮助将来遇到同样问题的人。