2

I'm trying to preload assemblies in a background thread and it seems that when the PreLoadAssemblies function is being called nothing happen and like the thread is dead or something (but I do see the thread in the threads list). When I run the code in single threaded environment, it's works fine.

Here is where I create the background call:

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

Here is the background initialization function. It stops (meaning, nothing happen and I see my dialog window progress bar running "on empty") after I try to step-in through the PReLoadAssemblies).

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

here is how preloadassemblies looks like:

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

Let me know if you have any idea.

Thanks

H H
  • 263,252
  • 30
  • 330
  • 514
Or A
  • 1,789
  • 5
  • 29
  • 55
  • 1
    What is the `PreLoadAssemblies` method? – SLaks Nov 02 '10 at 15:02
  • 1
    Two questions: Have you checked that the InitlaizePoint method is ever called? Have you put a breakpoint on the try line in the DoWork method to ensure that the DoWork method is called at all? The setup itself looks fine. – Øyvind Bråthen Nov 02 '10 at 15:03
  • the preload assembles is basically pre-load all the referenced assemblies into the memory. – Or A Nov 02 '10 at 15:24
  • That tells us nothing. Where does the progressbar come in? – H H Nov 02 '10 at 15:26

3 Answers3

4

Where exactly are you calling this method? The BackgroundWorker class needs the message pump already running, and will not work if you call it too early in your application (before Application.Run()).

If you are doing this from something like a splash screen that is run before the main application starts, unfortunately, you will need to do your own threading instead of using BackgroundWorker.

Note: As Henk Holterman points out, if you don't have a message pump at all (because you have a console app instead of Winforms or WPF), than BackgroundWorker will not work at all in your app.

M-Peror
  • 712
  • 8
  • 16
  • yes, i do call it from a splash screen which runs before the main app starts, but why the background worker won't work? it doesn't work even when i use my own threading. – Or A Nov 02 '10 at 15:26
  • I am having trouble finding where I read that, but the BackgroundWorker is specifically designed to be used from the UI thread in i.e. a WinForms application. I guess it uses the message loop to communicate its events to/from the UI thread. So before Application.Run(), it probably gets created, but never gets signaled to start. Using a System.Threading.Thread instead of a BackgroundWorker is probably the way to go. – M-Peror Nov 02 '10 at 15:58
1

We are looking at a edited version of your code. You removed the bits that cause the deadlock. Some notes:

  • You mention a 'status progress bar' but your code shows no evidence for it. Getting that bar updated provides ample ways for deadlock.
  • The commented calls to PublishStatus are a red flag
  • There is no evidence of a RunWorkerCompleted event handler even though you'd need one to get your splash screen closed. The BGW will deadlock when your main thread is blocking on the BGW and not pumping messages
  • There's a corner case for circular dependencies between assemblies. Your code will hang in an endless loop. Diagnose with Build + Clean, Build + Build.
  • Remote, but several .NET assemblies as well as C++/CLI assemblies have a module initializer. It may not necessarily act properly when the assembly is loaded on a non-STA worker thread.

RunWorkerCompleted is my best guess until you show an unedited version of your code.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
0

You cannot pre-load assemblies that easily. Take a look at my question.

Community
  • 1
  • 1
Oliver
  • 43,366
  • 8
  • 94
  • 151