我在一个埋藏在.dll中的类中有一个耗时的方法,我没有源代码。我在调用此方法时不想阻止UI。我一直在尝试使用BackgroundWorker来做到这一点。我从btn_Click事件处理程序调用RunWorkerAsync。当我在工作线程之外创建了dllClass实例(如下所示)时,UI会冻结,直到操作完成。该操作还会阻止计时器滴答作响。
public static dllClass dllClassInstance = new dllClass();
void worker1_DoWork(object sender, DoWorkEventArgs e)
{
dllClassInstance.TimeConsumingMethod();
}
另一方面,如果我在工作线程中实例化类(如下一个代码段),它就会按预期工作。
void worker1_DoWork(object sender, DoWorkEventArgs e)
{
dllClass dllClassInstance = new dllClass();
dllClassInstance.TimeConsumingMethod();
}
使用后者的问题是我需要访问该特定worker之外的类实例,因为我必须在耗时的方法之前和之后调用其他方法。我还尝试通过e.Argument将类实例传递给BackgroundWorker,但它也导致UI冻结。有没有人建议如何在不阻止UI的情况下调用该方法?
答案 0 :(得分:3)
有没有人建议如何在不阻止用户界面的情况下调用该方法?
在不知道dllClass
内发生了什么的情况下,无法确定。
通常,这两种代码都不会导致UI冻结。我怀疑dllClass
正在捕获其构造函数中的当前SynchronizationContext
,并在TimeConsumingMethod
内部使用它,导致阻塞。如果是这种情况,您可能会在DoWork处理程序中构造该类,但是将其作用于该类,这可能会起作用。但是,如果它正在捕获同步上下文,则该类可能具有线程关联性,并且期望在UI线程上运行。
您可以尝试在处理程序中构建实例,如下所示:
public dllClass dllClassInstance;
void worker1_DoWork(object sender, DoWorkEventArgs e)
{
dllClassInstance = new dllClass(); // Construct here
dllClassInstance.TimeConsumingMethod();
}
这可能有用,但正如我所说,它可能有其他副作用。我会验证dllClass
没有线程关联规则,要求它在UI线程上运行。
答案 1 :(得分:1)
这可能是因为你的dllClass
。除非有人想确保在同一个线程中处理实例上的所有调用,否则不应该发生这种情况。如果dllClass
在其构造函数中接受调度程序,然后TimeConsumingMethod
通过该调度程序调用实际处理,那么您将看到冻结的UI。
答案 2 :(得分:0)
正如里德指出的那样,如果不知道那个班级的内部是什么,可能很难真正解决。但是,如果你有其他东西需要加载/准备,设置,我会让你的后台工作者类“ReportsProgress”= true,当它启动时,立即调用一个方法来获取和/或准备基于ex的其他设置:进度为1(开始),然后,执行长进程的其他元素,然后报告进度值为99(结束)并从中进行清理。
这听起来有点像帮助吗?您仍然可以将它全部封装到一个后台工作者类中。
答案 3 :(得分:0)
我正在研究VB.net应用程序,并遇到与Visa Com 3.0驱动程序相同的问题,以便与安捷伦设备进行通信。以下是我解决它的方法:
Dim task = New Threading.Tasks.Task(Of dllClass)(Function()
Return New dllClass()
End Function)
task.Start()
task.Wait()
public static dllClass dllClassInstance = task.Result;
void worker1_DoWork(object sender, DoWorkEventArgs e)
{
dllClassInstance.TimeConsumingMethod();
}
基本上我在一个新线程中创建我的dllClass实例,但是立即丢弃该线程并保留引用。