2012-06-12 46 views
2

我有一个耗费时间的方法,它埋在一个.dll文件中,我没有它的源代码。当我调用此方法时,我不想阻止用户界面。我一直在尝试使用BackgroundWorker来做到这一点。我从btn_Click事件处理程序调用RunWorkerAsync。当我在工作线程之外创建dllClass实例时(如下所示),UI将冻结,直到操作完成。该操作还会阻止定时器发出滴答声。我的BackgroundWorker仍然阻止了我的用户界面

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(); 
} 

使用后者的问题是,我需要一个特定的工人外访问类的实例,因为我之前和耗时的方法后调用其他方法。我也尝试通过e.Argument将类实例传递到BackgroundWorker,但它也导致UI冻结。有没有人有建议如何调用该方法,而不会阻止用户界面?

+0

真正的解决方案是更改TimeConsumingMethod ...它正在做一些导致此问题的事情。你能告诉我们那个代码吗? –

+1

@RobertLevy引用OP:“......在一个埋在.dll中的类中,我没有它的源代码。” :( – Crisfole

+1

我会使用反射工具,并深入挖掘dll看看它在做什么 – tsells

回答

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线程上运行。

+0

这有点帮助当我尝试这个UI没有冻结,我可以在后台线程之外使用类实例_after_我运行了worker。我仍然遇到的问题是当我需要将实例用于其他事情时_before_我称为后台工作者 – user1451772

+1

@ user1451772您必须在后台线程或其他奇怪的东西中构建它。我会调查为什么'dllClass'首先造成这种情况... –

1

这可能是因为你的dllClass。你所看到的不应该发生,除非有人想确保实例上的所有调用都在同一个线程中处理。如果dllClass在其构造函数中接收调度程序,然后TimeConsumingMethod调用通过该调度程序的实际处理,那么您将看到冻结的UI。

0

正如里德指出的,如果不知道该类内部是什么,可能很难真正解决。然而,如果你有其他东西需要加载/准备,设置,我会让你的后台工作者类“ReportsProgress”= true,并且当它启动时,立即调用一个方法来抓取和/或准备其他设置:1(开始)的进度,然后,做你的长期过程的其他元素,然后报告像99(结束)值出来的进展,并从中做一些清理。

这听起来像它会帮助吗?你仍然可以将它封装到一个单一的后台工作者类中。

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实例,但立即丢弃线程,扶住参考。

+0

您应该使用Task.Factory.StartNew(或者如果在.NET 4.5中为Task.Run)创建并启动任务,而不是构造函数,也可以避免将任务存储在变量中。 – Servy

+0

我将如何收集结果? –

相关问题