【发布时间】:2017-07-26 17:33:52
【问题描述】:
背景
目前正在开发我要求创建的 Windows 窗体应用程序。当调用资源密集型进程时,我遇到了 UI 冻结的问题。我目前正在使用我理解的线程来防止 UI 冻结并接管整个电脑。
问题
目前,当我使用线程调用基类中的一个方法时,该方法是打开位于远程服务器上的文件。此方法有大约 30 到 45 秒的延迟。我正在创建我的后台线程并调用它来启动。当被调用以启动时如果触发,但是当它触发时它不会等待我的线程完成基本上给我一个空异常。因此,经过一番挖掘,我发现为了等待线程完成,您必须调用.Join()。但是,当调用 Join 时,它完全冻结了我的 UI。所以我的聪明才智试图创建一个解决方法并创建一个 while 循环,直到线程不再活动并继续。但是,这也冻结了 UI。所以我错过了什么吗? MSDN Doc中没有提到这一点
代码示例
class BaseClass
{
public CWClient ClientFileContext(string clientFile, bool compress)
{
Client clientContext = null;
try
{
if (compress == true)
{
clientContext = appInstance.Clients.Open2(clientFile, superUser, passWord, OpenFlags.ofCompressed);
}
else
{
clientContext = appInstance.Clients.Open2(clientFile, superUser, passWord, OpenFlags.ofNone);
}
}
catch (Exception ex)
{
//TODO
}
return clientContext;
}
}
public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs e)
{
BaseClass wpSec = new BaseClass();
CWClient client = null;
Thread backgroundThread = new Thread(
new ThreadStart(() =>
{
client = wpSec.ClientFileContext(selectedFileFullPath, true);
}
));
backgroundThread.Start();
//backgroundThread.Join(); << Freezes the UI
var whyAreYouNotWorking = "Stop";
}
}
我尝试过的解决方法
while (backgroundThread.IsAlive == true)
{
for (int n = 0; n < 100; n++)
{
Thread.Sleep(500);
progressBar1.BeginInvoke(new Action(() => progressBar1.Value = n));
}
}
// This also freezes the UI
【问题讨论】:
-
是的,加入(在开始后立即)否定了整个线程设置。你期待什么?它还会使任何 Control.Invoke() 调用死锁。
-
这里的简单答案是使用 BackgroundWorker
-
所以你知道如果你阻塞你的 UI 线程并强制它在后台工作完成之前什么都不做,你的 UI 就会被冻结,如果你不这样做,它就不会。所以……你有什么问题。您已经知道如何解决您的问题,不要阻塞 UI 线程。您已经展示了不自己阻塞 UI 线程的代码。
-
@Servy 正确我没有阻塞 UI,但是我仍然需要从我启动的线程加载结果。
-
@EasyE 从后台线程执行此操作,而不是在后台线程完成之前阻止 UI 线程执行任何操作。
标签: c# multithreading winforms