我遇到了问题而且不知道如何解决这个问题。我正在开始一个新的主题:
private void button_Click(object sender, EventArgs e)
{
Thread thrd = new Thread(new ThreadStart(loadingScreenStart));
thrd.Start();
//setting some variables, entering some methods etc...
thrd.Abort();
}
public void loadingScreenStart()
{
splashScreen splashObj = splashScreen.GetInstance();
Application.Run(splashScreen.GetInstance());
}
我有另一种形式:
private static splashScreen m_instance = null;
private static object m_instanceLock = new object();
public static splashScreen GetInstance()
{
lock (m_instanceLock)
{
if (m_instance == null)
{
m_instance = new splashScreen();
}
}
return m_instance;
}
这样可以正常工作,但是当我第二次按下按钮时,我得到一个例外,即无法访问被丢弃的对象。为什么以及如何解决这个问题?我的意思是在线程中止后,我再次点击按钮时创建一个新的。
答案 0 :(得分:0)
它不是被丢弃的线程,而是splashScreen
实例。你应该创建一个新的,而不是尝试重用旧的。
答案 1 :(得分:0)
Thread thrd = new Thread(new ThreadStart(loadingScreenStart));
thrd.Start();
//setting some variables, entering some methods etc...
thrd.Abort();
你为什么叫thrd.Abort()?你知道线程完成吗? 你必须等待线程完成。 并在这里使用双重检查
public static splashScreen GetInstance()
{
if (m_instance == null)
{
lock (m_instanceLock)
{
if (m_instance == null)
{
m_instance = new splashScreen();
}
}
}
return m_instance;
}
也许当你打电话给Run splashscreen时,它被处理掉了。尝试创建并将其捕获到字段并将其传递给您的方法。试试这个。
Task.Run(() =>
var splashObj = splashScreen.GetInstance();
Application.Run(splashObj);
}));
答案 2 :(得分:0)
好的我以某种方式解决了它。不要认为这是一个很好的解决方案,但它确实有效。我只是隐藏SplashScreen的Form并检查线程是否已经运行,而不是中止线程。如果是,那么我只是显示表格。如果不是,我创建一个新实例。
答案 3 :(得分:0)
这太复杂而且不安全。如果你真的想用“闪屏”处理这个问题,为什么不试试这样的东西?
using (var splashScreenForm = SplashScreen.ShowSplashScreen())
{
// Do your work
}
SplashScreen
有这样的方法:
public static SplashScreen ShowSplashScreen()
{
var form = new SplashScreen();
new Thread(() => Application.Run(form)).Start();
return form;
}
public override void Dispose(bool disposing)
{
if (disposing)
{
if (InvokeRequired)
{
Invoke(() => base.Dispose(true));
return;
}
base.Dispose(true);
}
else base.Dispose(disposing);
}
答案 4 :(得分:0)
再看看整个事情,我意识到这里还有另一个问题,这是完全错误的方向。
在您的button_Click
活动中,您显然会做很多复杂的事情,需要花费很多时间。否则你不需要显示启动画面。但是,在事件处理程序中执行此操作本身并不是一个坏主意。你完全锁定了UI线程,Windows很快就会认为该窗口被挂起了#34;。它甚至无法重画!
所以你应该从完全相反的方向接近这个。在使用UI线程进行繁重的工作时,不要试图从另一个线程显示启动画面,只需将繁重的工作移动到另一个线程!然后,启动画面不需要任何异国情调,比如在另一个帖子中调用Application.Start()
。只需一个简单的.ShowModal()
即可。当其他线程完成其工作时,它只能在启动画面上调用.Close()
。
在设计良好的应用程序中,几乎不需要第二个UI线程。需要将繁重的工作转移到其他线程,而不是UI。
请注意,如果您想从另一个线程操纵UI,您需要做一些Invoke()
的事情。在此处阅读更多内容:https://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired(v=vs.110).aspx