【问题标题】:BackgroundWorker is not being calledBackgroundWorker 没有被调用
【发布时间】:2010-11-02 15:00:34
【问题描述】:

我正在尝试在后台线程中预加载程序集,并且似乎在调用 PreLoadAssemblies 函数时没有发生任何事情,就像线程死了一样(但我确实在线程列表中看到了线程)。当我在单线程环境中运行代码时,它工作正常。

这里是我创建后台调用的地方:

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

这是预加载程序集的样子:

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

如果您有任何想法,请告诉我。

谢谢

【问题讨论】:

  • PreLoadAssemblies 方法是什么?
  • 两个问题:您是否检查过 InitlaizePoint 方法是否被调用过?你有没有在 DoWork 方法的 try 行设置断点,以确保 DoWork 方法被完全调用?设置本身看起来不错。
  • 预加载程序集基本上是将所有引用的程序集预加载到内存中。
  • 这并没有告诉我们什么。进度条从哪里来?

标签: c# multithreading backgroundworker


【解决方案1】:

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

如果您是在主应用程序启动之前运行的启动屏幕等执行此操作,很遗憾,您将需要执行自己的线程而不是使用 BackgroundWorker。

注意:正如 Henk Holterman 指出的那样,如果您根本没有消息泵(因为您有一个控制台应用程序而不是 Winforms 或 WPF),那么 BackgroundWorker 将根本无法工作在您的应用中。

【讨论】:

  • 是的,我确实从在主应用程序启动之前运行的初始屏幕调用它,但为什么后台工作人员无法工作?即使我使用自己的线程,它也不起作用。
  • 我很难找到我在哪里读到的,但 BackgroundWorker 是专门设计用于从 UI 线程中使用的,即 WinForms 应用程序。我猜它使用消息循环将其事件与 UI 线程进行通信。因此,在 Application.Run() 之前,它可能已创建,但从未收到启动信号。使用 System.Threading.Thread 而不是 BackgroundWorker 可能是要走的路。
【解决方案2】:

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

  • 您提到了“状态进度条”,但您的代码没有显示任何证据。更新该栏为死锁提供了充足的方法。
  • 对 PublishStatus 的评论调用是一个危险信号
  • 没有证据表明 RunWorkerCompleted 事件处理程序,即使您需要一个来关闭启动屏幕。当您的主线程在 BGW 上阻塞并且不发送消息时,BGW 将死锁
  • 程序集之间存在循环依赖关系的极端情况。您的代码将陷入无限循环。使用构建 + 清理、构建 + 构建进行诊断。
  • 远程,但一些 .NET 程序集以及 C++/CLI 程序集具有模块初始化程序。当程序集加载到非 STA 工作线程上时,它可能不一定会正常运行。

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

【讨论】:

    【解决方案3】:

    您不能那么容易地预加载程序集。看看my question

    【讨论】:

      猜你喜欢
      • 2017-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-15
      • 1970-01-01
      • 1970-01-01
      • 2018-11-25
      • 2019-03-31
      相关资源
      最近更新 更多