I've got thread, which processes some analytic work.
private static void ThreadProc(object obj)
{
var grid = (DataGridView)obj;
foreach (DataGridViewRow row in grid.Rows)
{
if (Parser.GetPreparationByClientNameForSynonims(row.Cells["Prep"].Value.ToString()) != null)
UpdateGridSafe(grid,row.Index,1);
Thread.Sleep(10);
}
}
I want safely update my gridView at loop, so I use classic way:
private delegate void UpdateGridDelegate(DataGridView grid, int rowIdx, int type);
public static void UpdateGridSafe(DataGridView grid, int rowIdx, int type)
{
if (grid.InvokeRequired)
{
grid.Invoke(new UpdateGridDelegate(UpdateGridSafe), new object[] { grid, rowIdx, type });
}
else
{
if (type == 1)
grid.Rows[rowIdx].Cells["Prep"].Style.ForeColor = Color.Red;
if (type==2)
grid.Rows[rowIdx].Cells["Prep"].Style.ForeColor = Color.ForestGreen;
}
}
But when I enter UpdateGridSafe, the program hangs.
In the debugger, I see that grid.Invoke doesn't invoke UpdateGridSafe. Please help - what's wrong?
EDIT
Classic thread create code
Thread t = new Thread(new ParameterizedThreadStart(ThreadProc));
t.Start(dgvSource);
t.Join();
MessageBox.Show("Done", "Info");
You have a deadlock. Your t.Join is blocking the GUI thread until ThreadProc is done. ThreadProc is blocked waiting for t.Join to finish so it can do the Invokes.
Bad Code
Thread t = new Thread(new ParameterizedThreadStart(ThreadProc));
t.Start(dgvSource);
t.Join(); <--- DEADLOCK YOUR PROGRAM
MessageBox.Show("Done", "Info");
Good Code
backgroundWorker1.RunWorkerAsync
private void backgroundWorker1_DoWork(object sender,
DoWorkEventArgs e)
{
var grid = (DataGridView)obj;
foreach (DataGridViewRow row in grid.Rows)
{
if (Parser.GetPreparationByClientNameForSynonims(row.Cells["Prep"].Value.ToString()) != null)
UpdateGridSafe(grid,row.Index,1);
// don't need this Thread.Sleep(10);
}
}
private void backgroundWorker1_RunWorkerCompleted(
object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done", "Info");
}
EDIT
Also use BeginInvoke instead of Invoke. That way your worker thread doesn't have to block every time you update the GUI.
Reference
Avoid Invoke(), prefer BeginInvoke()
It's because you're joining on your worker thread. Your UI thread starts the background thread, then calls Join on it. This stops the UI thread from performing any other actions.
During this, the background thread is doing its work and calling Invoke, which waits for the UI thread to respond. Because the UI thread is waiting for a Join, it won't ever process the request to invoke. Hence, deadlock.
What you should do, is eliminate the Join and the MessageBox. Put the MessageBox into its own function.
void NotifyDone() {
if( InvokeRequired ) BeginInvoke( (MethodInvoker) NotifyDone );
else {
// Perform any post-processing work
MessageBox.Show("Done", "Info");
}
}
When the background thread is done, simply call this method (and eliminate static from ThreadProc).
private void ThreadProc(object obj)
{
var grid = (DataGridView)obj;
foreach (DataGridViewRow row in grid.Rows)
{
if (Parser.GetPreparationByClientNameForSynonims(row.Cells["Prep"].Value.ToString()) != null)
UpdateGridSafe(grid,row.Index,1);
Thread.Sleep(10);
}
NotifyDone();
}
And like everyone else has already said, the use of Sleep, especially at such a low interval is either dangerous, misleading or worthless. I'm in the count it worthless camp.
The Invoke statement will wait until the main thread's message pump isn't busy, and can handle a new message. If your main thread is busy, the Invoke will hang.
In your case, it looks like your top code is running in a tight loop, so there's never a chance for the Invoke in the bottom code to actually run. If you change the Thread.Sleep in your upper code block to something with a time in it, hopefully that will give your main thread a chance to handle the .Invoke call.
Depending on what your main application thread is doing, you may need to actually finish your first loop before any of the .Invoke calls will run - if that's the case, I can post some modified code that might work better.
Never, ever, every use Thread.Sleep(0). It doesn't do what you think it does and will cause you nothing but pain. For example, in a tight loop the OS may decide that the thread that just slept is the next one to run. As a result you won't actually yield the thread.
Try your code again using Thread.Sleep(1) every N iterations where N is about 0.25 to 1.0 seconds worth of work.
If that doesn't work let me know and we can look at how ThreadProc is created.
References
Never Sleep(0) in an Infinite Loop
EDIT
Argument for never using Thread.Sleep
Thread.Sleep is a sign of a poorly designed program.
You also could be having issues accessing the grid at the same time from different threads. DataTables are not thread safe, so I'd guess that DataGridView isn't either. Here's some sample code from this article on DataRow and Concurrency where you would use Monitor.Enter and Montori.Exit to get some concurrency in place.
public void DoWorkUpdatingRow(object state)
{
List<DataRow> rowsToWorkOn = (List<DataRow>)state;
foreach (DataRow dr in rowsToWorkOn)
{
Monitor.Enter(this);
try
{
dr["value"] = dr["id"] + " new value";
}
finally
{
Monitor.Exit(this);
}
}
}
Related
I am trying to end my Thread, within the thread, and when aborted, i want to detect that the thread has been aborted (or just, stopped really)
This is what i am doing to do that, but isnt working as it never gets to this part
if (!thread.IsAlive){
CommandPrompt.SayMessage("Oops! MBP thread died.");
}
This is how i'm going about it, thank you for the help. sorry if my question is confusing please ask questions so i can help you help me :) thanks!
public static Thread thread;
public static void 1()
{
thread = new Thread(thread1);
thread.Start();
if (!thread.IsAlive)
{
CommandPrompt.SayMessage("Oops! MBP thread died.");
}
}
public static void thread1()
{
{
int test = 0;
while (thread.IsAlive){
Console.WriteLine("running.."); // this text will be displayed when the thread is active, and will stop when stopped.
Thread.Sleep(2500);
test += 1;
if (test > 4) // after 4 loops, i want the thread to end itself
thread.Abort();
}
if (!thread.IsAlive){ // once the thread is ended i want it to tell us that, but it never gets to this part.
CommandPrompt.SayMessage("Oops! MBP thread died.");
}
}
}
If you want to check if a thread is still alive, you cannot do that from the code running in that particular thread. Because, if you can execute the code to check if the thread is still alive, it is -- obviously -- still alive. And if the thread is not alive anymore it will -- obviously -- not be able to execute any more code ...
So the only way is to do this from somewhere outside the thread (ie some other thread, maybe even the main thread).
Just schematic code, which is rather clumsy, but will give you a first idea of how you can address this issue. But if there is a third party messing around with your threads, that won't help anything, because what prevents them from killing off your whole application?
public class ThreadTest {
static bool ranToEnd = false;
public static void Main(){
var thread = new Thread(aThread);
var lc = 1;
thread.Start();
while (true){
if (!aThread.IsAlive) {
if (ranToEnd)
Console.WriteLine("aThread terminated normally");
else
Console.WriteLine("aThread ended prematurely");
break;
} else if (++lc == 10) {
aThread.Abort(); //Simulating the abortion of the thread
}
Thread.Sleep(1000);
}
}
public static void aThread() {
//do some work in this thread
// if the thread ran to an end normally, this will be set to true
// if the thread ended prematurely, this will stay false ...
ranToEnd = true;
}
}
I want to use BackgroundWorker in my application. And I've learned, that when I want to do this:
buttonStart.Enabled = false;
in main thread, with another thread I should do it like this:
if (buttonStart.InvokeRequired) { buttonStart.Invoke(new Action(() => buttonStart.Enabled = false)); }
else buttonStart.Enabled = false;
But when it goes to comparision operations:
if(tabControlDbSwitch.SelectedIndex == 0)
it doesn't works.
So, here is my question:
if ((!tabControlDbSwitch.InvokeRequired && tabControlDbSwitch.SelectedIndex == 0) ||
(tabControlDbSwitch.InvokeRequired && /*What should I write here?*/))
And maybe you've got some hints for me, 'cause I'm totally newbie in multi threading, but I want to learn it as fast as possible.
I.e. I've heard that sometimes it will be better to use BeginInvoke than Invoke, but I don't know why and when.
CheckSelection is the function that you invoke from the function where this if code was return
public void CheckSelection()
{
if (tabControlDbSwitch.InvokeRequired)
{
tabControlDbSwitch.Invoke(new Action(() => { CheckTabSelection(); }));
}
else
CheckTabSelection();
}
public void CheckTabSelection()
{
if (tabControlDbSwitch.SelectedIndex == 0)
{
// Do my work .....
}
}
You said you have heard that sometimes it will be better to use BeginInvoke than Invoke, but I don't know why and when. invoke and begin invoke are of two types delegate and control. In your example you are using Contol.Invoke
Delegate.Invoke: Executes synchronously, on the same thread.
Delegate.BeginInvoke: Executes asynchronously, on a threadpool thread means the function that is invoked in begin invoke will be executed on a new thread from a thread pool and you can continue doing your operation on same thread (Parallel execution).
Control.Invoke: Executes on the UI thread, but calling thread will wait for completion of the invoked function before continuing.
Control.BeginInvoke: Executes on the UI thread, and calling thread will not wait for completion of invoked function.
Yes it is advisable that we use Control.BeginInvoke rather then Control.Invoke as you don't have to worry about deadlocks.
For example, if you remove the code
if(tabControlDbSwitch.InvokeRequired)
and always use
tabControlDbSwitch.Invoke(new Action(() => { CheckTabSelection(); }));
and in some case this function is invoked from UI main thread then your code will hang and result in deadlock.
Here's another approach that actually allows the Invoke() to RETURN a value.
This way your code flows a little better:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (GetSelectedIndex(this.tabControlDbSwitch) == 0)
{
Console.WriteLine("Success!");
}
}
private delegate int ReturnSelectedIndex(TabControl tb);
private int GetSelectedIndex(TabControl tb)
{
if (tb.InvokeRequired)
{
return (int)tb.Invoke(new ReturnSelectedIndex(GetSelectedIndex), new Object[] { tb });
}
else
{
return tb.SelectedIndex;
}
}
More newbie questions:
This code grabs a number of proxies from the list in the main window (I couldn't figure out how to make variables be available between different functions) and does a check on each one (simple httpwebrequest) and then adds them to a list called finishedProxies.
For some reason when I press the start button, the whole program hangs up. I was under the impression that Parallel creates separate threads for each action leaving the UI thread alone so that it's responsive?
private void start_Click(object sender, RoutedEventArgs e)
{
// Populate a list of proxies
List<string> proxies = new List<string>();
List<string> finishedProxies = new List<string>();
foreach (string proxy in proxiesList.Items)
{
proxies.Add(proxy);
}
Parallel.ForEach<string>(proxies, (i) =>
{
string checkResult;
checkResult = checkProxy(i);
finishedProxies.Add(checkResult);
// update ui
/*
status.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action(
delegate()
{
status.Content = "hello" + checkResult;
}
)); */
// update ui finished
//Console.WriteLine("[{0}] F({1}) = {2}", Thread.CurrentThread.Name, i, CalculateFibonacciNumber(i));
});
}
I've tried using the code that's commented out to make changes to the UI inside the Parallel.Foreach and it makes the program freeze after the start button is pressed. It's worked for me before but I used Thread class.
How can I update the UI from inside the Parallel.Foreach and how do I make Parallel.Foreach work so that it doesn't make the UI freeze up while it's working?
Here's the whole code.
You must not start the parallel processing in your UI thread. See the example under the "Avoid Executing Parallel Loops on the UI Thread" header in this page.
Update: Or, you can simply create a new thread manuall and start the processing inside that as I see you have done. There's nothing wrong with that too.
Also, as Jim Mischel points out, you are accessing the lists from multiple threads at the same time, so there are race conditions there. Either substitute ConcurrentBag for List, or wrap the lists inside a lock statement each time you access them.
A good way to circumvent the problems of not being able to write to the UI thread when using Parallel statements is to use the Task Factory and delegates, see the following code, I used this to iterate over a series of files in a directory, and process them in a Parallel.ForEach loop, after each file is processed the UI thread is signaled and updated:
var files = GetFiles(directoryToScan);
tokenSource = new CancellationTokenSource();
CancellationToken ct = tokenSource.Token;
Task task = Task.Factory.StartNew(delegate
{
// Were we already canceled?
ct.ThrowIfCancellationRequested();
Parallel.ForEach(files, currentFile =>
{
// Poll on this property if you have to do
// other cleanup before throwing.
if (ct.IsCancellationRequested)
{
// Clean up here, then...
ct.ThrowIfCancellationRequested();
}
ProcessFile(directoryToScan, currentFile, directoryToOutput);
// Update calling thread's UI
BeginInvoke((Action)(() =>
{
WriteProgress(currentFile);
}));
});
}, tokenSource.Token); // Pass same token to StartNew.
task.ContinueWith((t) =>
BeginInvoke((Action)(() =>
{
SignalCompletion(sw);
}))
);
And the methods that do the actual UI changes:
void WriteProgress(string fileName)
{
progressBar.Visible = true;
lblResizeProgressAmount.Visible = true;
lblResizeProgress.Visible = true;
progressBar.Value += 1;
Interlocked.Increment(ref counter);
lblResizeProgressAmount.Text = counter.ToString();
ListViewItem lvi = new ListViewItem(fileName);
listView1.Items.Add(lvi);
listView1.FullRowSelect = true;
}
private void SignalCompletion(Stopwatch sw)
{
sw.Stop();
if (tokenSource.IsCancellationRequested)
{
InitializeFields();
lblFinished.Visible = true;
lblFinished.Text = String.Format("Processing was cancelled after {0}", sw.Elapsed.ToString());
}
else
{
lblFinished.Visible = true;
if (counter > 0)
{
lblFinished.Text = String.Format("Resized {0} images in {1}", counter, sw.Elapsed.ToString());
}
else
{
lblFinished.Text = "Nothing to resize";
}
}
}
Hope this helps!
If anyone's curious, I kinda figured it out but I'm not sure if that's good programming or any way to deal with the issue.
I created a new thread like so:
Thread t = new Thread(do_checks);
t.Start();
and put away all of the parallel stuff inside of do_checks().
Seems to be doing okay.
One problem with your code is that you're calling FinishedProxies.Add from multiple threads concurrently. That's going to cause a problem because List<T> isn't thread-safe. You'll need to protect it with a lock or some other synchronization primitive, or use a concurrent collection.
Whether that causes the UI lockup, I don't know. Without more information, it's hard to say. If the proxies list is very long and checkProxy doesn't take long to execute, then your tasks will all queue up behind that Invoke call. That's going to cause a whole bunch of pending UI updates. That will lock up the UI because the UI thread is busy servicing those queued requests.
This is what I think might be happening in your code-base.
Normal Scenario: You click on button. Do not use Parallel.Foreach loop. Use Dispatcher class and push the code to run on separate thread in background. Once the background thread is done processing, it will invoke the main UI thread for updating the UI. In this scenario, the background thread(invoked via Dispatcher) knows about the main UI thread, which it needs to callback. Or simply said the main UI thread has its own identity.
Using Parallel.Foreach loop: Once you invoke Paralle.Foreach loop, the framework uses the threadpool thread. ThreadPool threads are chosen randomly and the executing code should never make any assumption on the identity of the chosen thread. In the original code its very much possible that dispatcher thread invoked via Parallel.Foreach loop is not able to figure out the thread which it is associated with. When you use explicit thread, then it works fine because the explicit thread has its own identity which can be relied upon by the executing code.
Ideally if your main concern is all about keeping UI responsive, then you should first use the Dispatcher class to push the code in background thread and then in there use what ever logic you want to speedup the overall execution.
if you want to use parallel foreach in GUI control like button click etc
then put parallel foreach in Task.Factory.StartNew
like
private void start_Click(object sender, EventArgs e)
{
await Task.Factory.StartNew(() =>
Parallel.ForEach(YourArrayList, (ArraySingleValue) =>
{
Console.WriteLine("your background process code goes here for:"+ArraySingleValue);
})
);
}//func end
it will resolve freeze/stuck or hang issue
I have a BackgroundWorker DoWork function as follows
private void WorkerGetFeedData(object sender, DoWorkEventArgs args)
{
_feed.FetchUserData(_userNameCollection);
}
The FetchUserData is a function in another class(whose object is _feed) in another project in the same solution. The data fetch process takes considerable time and I'd like for the user to be able to cancel the process if necessary. How do I convey a cancel operation from the user to a function call elsewhere and just stop it?
You can use BackgroundWorker.CancelAsync method. Here's more info with example: MSDN
To be more exact to your problem, pass the worker to FetchUserData. It is the sender parameter. Then in the FetchUserData function you can check if the flag BackgroundWorker.CancellationPending is set and finish your method.
void FetchUserData(IEnumerable<Users> userNameCollection, BackgroundWorker worker)
{
// ...
if(worker.CancellationPending)
{
// Finish method..
}
}
And the WorkerGetFeedData method:
private void WorkerGetFeedData(object sender, DoWorkEventArgs args)
{
var worker = sender as BackgroundWorker;
if(worker != null)
_feed.FetchUserData(_userNameCollection, worker);
}
Send a message (event) to the worker thread that changes a boolean, indicating that the worker thread should end/cancel itself.
Edit: I was a bit quick reading your question, missing the important part. While trying to make up I found this interesting article which might help:
http://ondotnet.com/pub/a/dotnet/2003/02/18/threadabort.html
It does work when simulating a long running process with Thread.Sleep(), being at work I dont have time right now to write code to test it on a proper application/long running task.
class Program
{
static void Main(string[] args)
{
Thread thread = new Thread(new ThreadStart(Foo));
thread.Start();
Console.ReadKey();
thread.Abort(); // cause ThreadAbortException to be thrown
Console.ReadKey();
}
static void Foo()
{
try
{
while( true )
{
Console.WriteLine("Long running process...");
Thread.Sleep(100000);
}
}
catch( ThreadAbortException ex )
{
Console.WriteLine(ex.Message);
}
finally
{
Console.WriteLine("Thread Closing ...");
}
}
}
The problem with this approach is - it uses Thread.Abort() - which interrupts the thread no matter what it is doing. This can lead to left open handles, memory leaks, etc. So while it may help it would most likely be very unwise to use.
Ian Griffiths supposes that another way to (force) cancel a thread would be to run it in its own, seperate process: http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation which you can kill whenever without affecting your process's internal state.
In case of BackgroundWorker, a cancel can be reported by the e.Cancel - property of the DoWork - event handler.
How can I achieve the same thing with a Thread object?
Here is a full example of one way of doing it.
private static bool _runThread;
private static object _runThreadLock = new object();
private static void Main(string[] args)
{
_runThread = true;
Thread t = new Thread(() =>
{
Console.WriteLine("Starting thread...");
bool _localRunThread = true;
while (_localRunThread)
{
Console.WriteLine("Working...");
Thread.Sleep(1000);
lock (_runThreadLock)
{
_localRunThread = _runThread;
}
}
Console.WriteLine("Exiting thread...");
});
t.Start();
// wait for any key press, and then exit the app
Console.ReadKey();
// tell the thread to stop
lock (_runThreadLock)
{
_runThread = false;
}
// wait for the thread to finish
t.Join();
Console.WriteLine("All done.");
}
In short; the thread checks a bool flag, and keeps runing as long as the flag is true. I prefer this approach over calling Thread.Abort becuase it seems a bit nicer and cleaner.
Generally you do it by the thread's execute being a delegate to a method on an object, with that object exposing a Cancel property, and the long-running operation periodically chercking that property for tru to determine whether to exit.
for example
public class MyLongTunningTask
{
public MyLongRunninTask() {}
public volatile bool Cancel {get; set; }
public void ExecuteLongRunningTask()
{
while(!this.Cancel)
{
// Do something long running.
// you may still like to check Cancel periodically and exit gracefully if its true
}
}
}
Then elsewhere:
var longRunning = new MyLongTunningTask();
Thread myThread = new Thread(new ThreadStart(longRunning.ExecuteLongRunningTask));
myThread.Start();
// somewhere else
longRunning.Cancel = true;
A blocked thread can be stopped prematurely in one of two ways:
Thread.Interrupt
Thread.Abort
The main question is if the thread works on any ressources which need to be released correctly - in this case - you need to work with a property on the actual object which runs the thread.
There's Thread.Abort, which works by injecting a ThreadAbortException into the thread. It's a little risky because:
Your thread can get stuck if it's executing native code at the time
The code in the thread better be exception-safe, because this ThreadAbortException could happen on any line of code within it, even something innocent like i = i + 1
You're better off coding your own signalling mechanism between your GUI thread and the background thread. It's hard to recommend something without knowing what's going on inside that thread, but where I have a thread that works by waiting on some object in a loop, I use an AutoResetEvent and wait on that too.