Kasrak
Kasrak

Reputation: 1561

Use an extra thread and return back to the starter thread

Note : Although in some similar cases BackgroundWorker is recommended I prefer to do this job without it, cause this way I could make more generic code that could be used across my applications, and it will use my naming conventions.

What I want : Show my arraylist inside MyListBox via ShowResult(...) Method

What do you suggest as a best practice in this case

Also maybe I have to move the Focus Method right ater the thread.Start method, which I don't know

Sample code

btnPress Method :

        SetStatus(" Openning & Initializing the File");
        ThreadStart threadStart = new ThreadStart(HeavyProcess);
        threadProcess = new Thread(threadStart);
        threadProcess.Start();

HeavyProcess Method

    public void HeavyProcess()
    {
        SetStatus("Thread Started!");


        // Filling an ArrayList arrHealth ....            

        ShowResult(...);
        // Filling the ListBox with the ArrayList
        // At this time I want to be sure that the extra thread be finished and it 
        // returned to the GUI thread

The Cross-Thread Solution of mine :

public delegate void SetStatusDelegate(string text);

public void SetStatus(string stStatus)
{
    if (statLLS.InvokeRequired)
        statLLS.Invoke(new SetStatusDelegate(SetStatus),stStatus);
    else
        statLLS.Text = stStatus;
}

-- Edit --

Path1 :

The same as above

This will cause an error : Invalid Operation ... Cross-thread operation not valid ... When I want to access the ListBox and put the Arraylist result in it It shows that it's still in the extra thread how can I leave this "ShowResult(...); " for the main thread

Path2 :

        threadProcess.Start();                    
        ShowResult(...); 
        // Filling the ListBox with the ArrayList
        // the Watch shows that ArrayList is null

this will cause nothing !

Upvotes: 0

Views: 178

Answers (2)

Joshua Honig
Joshua Honig

Reputation: 13215

Your problem is in calling MyListBox.Focus() in the background thread. You can't do that with a Windows Forms app -- you must leave GUI handling to the main GUI thread. A more typical approach would be to poll or wait for the background thread to complete and then do the GUI stuff in the main thread. The point of a BackgroundWorker is that it makes this easy by providing things like the RunWorkerCompleted event to actively notify you when the thread is done.

Windows Forms does provide a specific mechanism for this kind of thing, though, with the Windows.Forms.Timer (NOT System.Timers.Timer). GUI actions performed by the event handlers attached to the Tick event, even though originating from a separate thread, will work.

Basically, the format is:

public partial class Form1 : Form {

    private Thread threadProcess;
    private System.Windows.Forms.Timer heavyProcessTimer = new Timer();

    public Form1() {
        InitializeComponent();
        heavyProcessTimer.Interval = 50; // or whatever
        heavyProcessTimer.Tick += new EventHandler(heavyProcessTimer_Tick);
    }

    void heavyProcessTimer_Tick(object sender, EventArgs e) {
        if (!threadProcess.IsAlive) {
            heavyProcessTimer.Stop();
            MyListBox.Focus();    
            ShowResult(...);
        }
    }

    private void btnPress(object sender, EventArgs e) {
        SetStatus(" Openning & Initializing the File"); 
        ThreadStart threadStart = new ThreadStart(HeavyProcess); 
        threadProcess = new Thread(threadStart); 
        threadProcess.Start();
        heavyProcessTimer.Start();
    }
}

Upvotes: 1

Jon
Jon

Reputation: 437376

If you want to be sure you are in the UI thread, just Invoke the code you want to run there (that's the very reason Invoke exists -- see also BeginInvoke).

This would probably not be the best solution (although there are too many possibilities to reach a verdict), but it would certainly work.

Upvotes: 2

Related Questions