Reputation: 1561
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
SetStatus(" Openning & Initializing the File");
ThreadStart threadStart = new ThreadStart(HeavyProcess);
threadProcess = new Thread(threadStart);
threadProcess.Start();
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
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
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