2010-11-02 91 views
2

我试图预加载组件在后台线程,似乎当PreLoadAssemblies函数被调用没有发生而像线程是死或某事(但我确实看到螺纹螺纹列表)。当我在单线程环境下运行代码时,它工作正常。的BackgroundWorker不会被调用

这里就是我创建背景呼叫:

BackgroundWorker backgroundWorker = new BackgroundWorker(); 
//[Threaded] 
private void InitlaizePoint() 
{ 
    backgroundWorker.DoWork += new DoWorkEventHandler(BackgroundInitalization); 
    backgroundWorker.RunWorkerAsync();   
} 

这里是后台初始化函数。它停下来(意思是什么都没有发生,我试着介绍PReLoadAssemblies后,我看到我的对话窗口进度条在“空”运行)。

private void BackgroundInitalization(object sender, DoWorkEventArgs e) 
{  
    try 
    { 
     PreLoadAssemblies(); 
    } 
    catch(Exception ex) 
    { 
     Console.WriteLine(ex.ToString()); 
    } 
} 

这里是preloadassemblies的样子:

private static void PreLoadAssemblies() 
{ 
    //statusController.PublishStatus("pre-loading assemblies"); 
    var missingAssemblies = new ArrayList(); 
    var loadedAssemblies = new ArrayList(); 
    LoadDependencies(Assembly.GetExecutingAssembly().GetName(), missingAssemblies, loadedAssemblies); 
} 

private static void LoadDependencies(AssemblyName name, ArrayList missingAssemblies, ArrayList loadedAssemblies) 
{ 
    try 
    { 
     //statusController.PublishStatus("Loading dependencies"); 

     Assembly a = Assembly.Load(name); 
     loadedAssemblies.Add(name.FullName); 
     foreach (AssemblyName depends in a.GetReferencedAssemblies()) 
     { 
      if (!IsAssemblyLoaded(depends.FullName, loadedAssemblies)) 
       LoadDependencies(depends, missingAssemblies, loadedAssemblies); 
     } 
    } 
    catch (Exception) 
    { 
     missingAssemblies.Add(name); 
    } 
} 

private static bool IsAssemblyLoaded(String name, ArrayList preloadedAssemblies) 
{ 
    if (preloadedAssemblies.IndexOf(name) == -1) 
     return false; 
    return true; 
} 

让我知道如果你有任何想法。

谢谢

+1

什么是PreLoadAssemblies方法? – SLaks 2010-11-02 15:02:07

+1

有两个问题:您是否检查过InitlaizePoint方法是否曾被调用过?您是否在DoWork方法的try线上放置了断点以确保DoWork方法完全被调用?设置本身看起来不错。 – 2010-11-02 15:03:06

+0

预加载组装基本上是将所有引用的组件加载到内存中。 – 2010-11-02 15:24:49

回答

3

你究竟在哪里调用这个方法? BackgroundWorker类需要消息泵已经运行,并且如果您在应用程序中(Application.Run()之前)过早调用该消息泵,将无法工作。

如果从这样的事情是运行启动画面做这个主应用程序开始前,不幸的是,你需要做你自己的线程,而不是使用的BackgroundWorker的。注意:正如Henk Holterman指出的那样,如果您没有的消息泵(因为您有一个控制台应用程序而不是Winforms或WPF),那么BackgroundWorker在您的应用程序中完全不起作用。

+0

是的,我确实从主应用程序启动之前运行的启动画面调用它,但为什么后台工作人员无法工作?即使当我使用自己的线程时,它也不起作用。 – 2010-11-02 15:26:37

+0

我很难找到我读的地方,但BackgroundWorker专门设计用于从UI线程(即WinForms应用程序)中使用。我想它使用消息循环来将其事件传递给UI线程。所以在Application.Run()之前,它可能会被创建,但永远不会被启动。使用System.Threading.Thread而不是BackgroundWorker可能是最好的选择。 – 2010-11-02 15:58:54

1

我们正在查看您的代码的编辑版本。您删除了造成死锁的位。一些注意事项:

  • 您提到了“状态进度栏”,但您的代码没有显示任何证据。获取更新栏提供了充足的死锁方式。
  • 对PublishStatus的评论性调用是红旗
  • 即使您需要关闭启动画面,也没有RunWorkerCompleted事件处理程序的证据。当BGW上的主线程阻塞并且不会泵送消息时,BGW会发生死锁
  • 组件之间存在循环依赖关系的转角情况。您的代码将无限循环地挂起。使用Build + Clean,Build + Build进行诊断。
  • 远程,但几个.NET程序集以及C++/CLI程序集都有一个模块初始化程序。当程序集加载到非STA工作线程时,它可能不一定正常工作。

RunWorkerCompleted是我最好的猜测,直到您显示未经编辑的代码版本。