简体   繁体   中英

Why isn't my multithreaded app doing what it should do?

I'm using the ThreadPool to manage my threads. Separately from the UI thread I have a thread that does data retrieval and general work operations and I have a 3rd thread that updates the UI to reflect the status of requested operations.

See code below:

// ui thread
private void btnLoadClients_Click(object sender, EventArgs e)
{
    // start thread 1
    ThreadPool.QueueUserWorkItem(new Form1().LoadClientList);
}

// thread 1
private void LoadClientList(object state)
{
    ThreadBusy = true;
    ThreadAction = "Loading Clients...";

    // start thread 2
    ThreadPool.QueueUserWorkItem(new Form1().ShowProgress);

    // get data
    ClientController c = new ClientController();
    List<Client> clients = c.GetClient();

    foreach (Client item in clients)
    {
        cmbClientList.Items.Add(item.Name);
    }
    cmbClientList.Items.Insert(0, "Please select a client");

    ThreadBusy = false;
}

// thread 2
private void ShowProgress(object state)
{
    while (ThreadBusy)
    {
        foreach (string action in lstAction.Items)
        {
            // write the action that's being taken to the listbox
            if (String.Compare(action, ThreadAction) != 0)
                lstAction.Items.Add(ThreadAction);
        }                
    }
}

Problem is that although ShowProgress is being hit when I set a breakpoint on it, execution isn't entering it really. The while (ThreadBusy) line isn't getting hit ever.

Have I got anything wrong here?

ThreadPool.QueueUserWorkItem(new Form1().LoadClientList);

ThreadPool.QueueUserWorkItem(new Form1().ShowProgress);

You're creating new Form1 instances every time you start a background thread, every action you take in these methods will happen to these new, "unbounded" instances, not on the one interacting with the user.

If you want to perform background work in WinForms you can leverage the BackgroundWorker class.

A really simple example:

public static class Program
{
    public static void Main()
    {
        var backgroundWorker = new BackgroundWorker();

        backgroundWorker.WorkerReportsProgress = true

        backgroundWorker.Disposed += BackgroundWorker_Disposed;
        backgroundWorker.DoWork += BackgroundWorker_DoWork;
        backgroundWorker.ProgressChanged += BackgroundWorker_ProgressChanged;
        backgroundWorker.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted;

        backgroundWorker.RunWorkerAsync();
    }

    private static void BackgroundWorker_Disposed(object sender, EventArgs e)
    {
        // Cleanup after yourself.
    }

    private static void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        // Do your things in background.
    }

    private static void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // Notify progress.
    }

    private static void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // The background task is complete ("successfully" is NOT implied).
    }
}

ThreadBusy property that you set to true belongs to a different Form1 object. because the thread that runs ShowProgress executes on a new instance of Form1 and its ThreadBusy property is false always. Thats why it is not entering into the while loop.

Can you try this

ThreadPool.QueueUserWorkItem(this.ShowProgress);

instead of

ThreadPool.QueueUserWorkItem(new Form1().ShowProgress);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM