Call a method running on another thread - c#

I am creating multiple different threads from a single manager class. I now need to update each thread when a variable in the parent application changes.
So I would like to be able to call a function within the thread. What is the best approach? The thread has a reference to the manager class so I was thinking to poll a function in the manager from within the thread to check for changes to the variable, but that doesn't seem right, surely there is a better way. I looked at Dispatcher class but this didn't seem right either. Can anyone recommend the best approach to this?
account1 = new Account(this);
account2 = new Account(this);
Thread accountThread1 = new Thread(new ThreadStart(account1.Run));
Thread accountThread2 = new Thread(new ThreadStart(account2.Run));
accountThread1.Start();
accountThread2.Start();
// How do I call method on accountThread1 or 2?

If i understand it right, you want a proper way to handle the threads.
I couldnt give to you the proper way, but this is the way im handling my threads to get data from PLC 24/7 without crash.
Sample as below:
//Create list of thread
private List<Thread> threads = new List<Thread>();
private void RunThread(YourClass yourclass)
{
switch (yourclass.ConnStat)
{
case ConnStatus.DISCONNECTED:
{
Thread oldthread = threads.FirstOrDefault(i => i.Name == yourclass.ID.ToString());
if (oldthread != null)
{
//Clean old thread
threads.Remove(oldthread);
}
else
{
//Add event here
yourclass.OnResponseEvent += new EventHandler<YourClass.ResponseEventArgs>(work_OnResponseEvent);
yourclass.OnNotificationEvent += new EventHandler<YourClass.NotificationEventArgs>(work_OnInfoEvent);
}
try
{
//Add thread to list
Thread thread = new Thread(new ThreadStart(() => yourclass.Initialize())) { Name = yourclass.ID.ToString(), IsBackground = true };
thread.Start();
threads.Add(thread);
Thread.Sleep(100);
}
catch (ThreadStateException ex)
{
MessageBox.Show(ex.Message);
}
break;
}
case ConnStatus.CONNECTED:
{
MessageBox.Show(string.Format("ID:{0}, is currently running!", yourclass.ID));
break;
}
case ConnStatus.AWAITING:
{
MessageBox.Show(string.Format("ID:{0}, is currently awaiting for connection!", yourclass.ID));
break;
}
}
}
//To control your class within thread
private void StopThread(YourClass yourclass)
{
if (yourclass.ConnStat == ConnStatus.CONNECTED || yourclass.ConnStat == ConnStatus.AWAITING)
{
//Call your method
yourclass.Disconnect();
yourclass.OnResponseEvent -= work_OnResponseEvent;
yourclass.OnDBResponseEvent -= work_OnDBResponseEvent;
yourclass.OnNotificationEvent -= work_OnInfoEvent;
Thread oldthread = threads.FirstOrDefault(i => i.Name == yourclass.ID.ToString());
if (oldthread != null) threads.Remove(oldthread);
}
}
Hope this helps

So the solution to this is to use an Observer Pattern to effectively push variable changes into the threads achieving the required results.
Using an Observer Pattern all the running threads can watch a variable in parent application for changes. This way the threads do not poll the parent, but the threads can respond to changes in a variable in the main application, effectively allowing push of changed variables into all of the threads.
The MS Docs link is a bit complex. I found this was quite a nice easy to follow tutorial:
https://www.youtube.com/watch?v=grHxRCtETP8

Related

A thread is still trying to access a disposed form?

Basically, I have a thread that downloads and reports the download status to a progress bar and a label. It always crashes when trying to invoke a object in a disposed form (Progress bar & label) even when there's a if (!this.Disposed) is called before, and still throws the exception even with a catch (ObjectDisposedException) is called in the same try block. I'm not sure what I can do to fix this, it's probably best described as the most annoying thing I've ever encountered.
Thanks you.
Update (from a considerate SO lurker) of my source found on pastebin
Thread downloader();
public bool abortThread = false();
private void frmDownload_FormClosing(object sender, FormClosingEventArgs e) {
downloader.Abort(); // Abort the thread before closing the form...?
abortThread = true; // Set the abortThread to true
this.Dispose(); // Dispose thread
}
downloader = new Thread(() => {
string[] URLs = { "http://test1.com/", "http://test2.com/", "http://test3.com/" };
try {
using (WebClient wc = new WebClient()) {
wc.DownloadProgressChanged += (s, e) => {
if (!pbDownloadStatus.IsDisposed && !lbPercentage.IsDisposed) {
if (!abortThread) {
this.Invoke((MethodInvoker)(() => pbDownloadStatus.Value = e.ProgressPercentage)); // EXCEPTION HAPPENS HERE
this.Invoke((MethodInvoker)(() => pbDownloadStatus.Value++));
this.Invoke((MethodInvoker)(() => pbDownloadStatus.Value--));
this.Invoke((MethodInvoker)(() => lbPercentage.Text = e.ProgressPercentage.ToString() + "%"));
}
}
};
wc.DownloadFileCompleted += (s, e) => {
if (!pbDownloadStatus.IsDisposed && !lbPercentage.IsDisposed) {
lock (e.UserState) {
this.Invoke((MethodInvoker)(() => pbDownloadStatus.Value = 0));
this.Invoke((MethodInvoker)(() => lbPercentage.Text = "0%"));
Monitor.Pulse(e.UserState);
}
}
};
wc.Proxy = WebProxy.GetDefaultProxy();
wc.Headers.Add(header);
for (int i = 0; i < URLs.Length; i++) {
var sync = new Object();
lock (sync) {
wc.DownloadFileAsycn(new Uri(URLs[i]), "C:\Test\URL" + i);
Monitor.Wait(sync);
}
}
}
}
}
catch (ObjectDisposedException disEx) { // Never gets caught
downloader.Abort();
MessageBox.Show("Object was disposed");
}
});
downloader.Start();
From Msdn
Beginning with the .NET Framework 4, multithreaded programming is
greatly simplified with the System.Threading.Tasks.Parallel and
System.Threading.Tasks.Task classes, Parallel LINQ (PLINQ), new
concurrent collection classes in the System.Collections.Concurrent
namespace, and a new programming model that is based on the concept of
tasks rather than threads
The need to work with threads directly in the modern era is greatly reduced, and you should probably look at Tasks and async/await Tasks can be cancelled, are easier to manage and async returns back to the calling context.
Secondly, your code doesn't make sense, and its full of compiler errors which is not a good start for a question. Additionally, since there is so much wrong with the code i have decided to just give you lots of points to think about apposed to rewriting it all
So lets look at some of the more obvious issues this code has.
abortThread is accessed from multiple threads and is not thread safe for the most part.
You are calling var sync = new Object(); directly before lock (sync) meaning you are locking nothing
Even if that lock statement was going to work, there is no other thread using the lock, meaning its redundant.
You are calling this.Dispose() from the forms closing event. This is unusal to say the least
The two conditions when a form is not disposed on Close is when (1) it
is part of a multiple-document interface (MDI) application, and the
form is not visible; and (2) you have displayed the form using
ShowDialog. In these cases, you will need to call Dispose manually to
mark all of the form's controls for garbage collection.
Basically in a non MDI application, If you call ShowDialog then put it in a using statement.
You are trying to check IsDisposed to determine if its safe to marshal back to the UI thread.
Just because you call Dispose doesn't mean the form IS disposed, this is not how it works and will not solve your problem.
If you need to do asynchronous IO bound work, Use the aysnc,await pattern, then you wont be blocking a thread for spurious reasons waiting for a completion port. If you need to run this in parallel, then consider DataFlow with action blocks so you can take advantage of aysnc,await and parallel.
If you need to determine whether a form is alive or dead, use a thread safe variable. Use a static Lock object, and every where you update the variable use lock as well.
if you need to marshal to the UI thread. Don't do this.Invoke((MethodInvoker)(() multiple times, Do it once, and update everything at once.

Reuse same single thread for same task again and again in wpf (c#) application without ThreadPool

Creating An MVVM application where application wants to connect to server on a button click. After clicking the button, a thread will be created to connect to the server so that UI doesn't freeze and terminates(TIME OUT is 15 secs). Next time click on the button is creating again new thread to connect to server and terminates.
But first time I want to create a new thread and later I want to reuse that thread(not new) to do the "connect" task if application is not closed and user clicked on the same button.
Is that possible?
Below is the code:
Class ConnectViewModel:BaseViewModel
{
public void ConnectToServer()
{
ConnectButtonEnable = false;
ConnectingServerText = Properties.Resources.TryingToConnectServer;
Thread thread = new Thread(new ThreadStart(connect));
thread.Start();
thread.Join();
}
public void connect()
{
bool bReturn = false;
UInt32 iCommunicationServer;
bReturn = NativeMethods.CommunicateServer(out iCommunicationServer);
if (!bReturn || NativeMethods.ERROR_SUCCESS != iCommunicationServer)
{
ConnectingServerText = Properties.Resources.UnableToConnectToServer;
}
else if (NativeMethods.ERROR_SUCCESS == iCommunicationServer)
{
ConnectingServerText = properties.Resources.SuccessfullyConnectedServer;
}
ConnectButtonEnable = true;
return;
}
}
Due to how the question is phrased I would recommend you to read up on MVVM and async patterns, some examples:
http://msdn.microsoft.com/en-us/magazine/dn605875.aspx
http://richnewman.wordpress.com/2012/12/03/tutorial-asynchronous-programming-async-and-await-for-beginners/
But in general, use async, don't manually create new threads when coding in a GUI-application. If the task shouldn't be callable whilst "running", do test and set via Interlocked.CompareExchange and store away some state.
You use threads for parallel work, not for "waiting on the network".
You can use the TPL to achieve this.
private Task previous = Task.FromResult(true);
public Task Foo()
{
previous = previous.ContinueWith(t =>
{
DoStuff();
});
return previous;
}
By having the operation schedule each operation as the continuation of the previous operation, you ensure that each one doesn't start until the one that came before it finished, while still running all of them in background threads.
Dont worry about creating and managing threads, just use ThreadPool.QueueUserWorkItem instead - its very efficient.

Suspending a thread in a wpf application

I have a WPF application in which i have this class :
public partial class Global : UserControl
{
public static List<Thread> listofthreads = new List<Thread>();
public Global()
{
InitializeComponent();
Thread windowThread = new Thread(delegate() { verifing(); });
listofthreads.Add(windowThread);
windowThread.Start();
}
public void verifing()
{
if (Global2.Pat_pathregfile.Length > 5 && Global2.Pat_pathcalibfile.Length > 5) {
if (utilisation.Dispatcher.CheckAccess())
{
utilisation.Visibility = Visibility.Visible;
}
else
{
utilisation.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
utilisation.Visibility = Visibility.Visible;
}));
}
foreach (Thread t in listofthreads) {
try
{
t.Suspend();
}
catch { }
}
}
else {
if (utilisation.Dispatcher.CheckAccess())
{
utilisation.Visibility = Visibility.Hidden;
}
else
{
utilisation.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
utilisation.Visibility = Visibility.Hidden;
}));
}
Thread windowThread = new Thread(delegate() { verifing(); });
windowThread.Start();
listofthreads.Add(windowThread);
}
}
}
i need to kill properly all of the threads that i have used
foreach (Thread t in listofthreads) {
try
{
t.Suspend();
}
catch { }
}
But the program indicates that the use of the method suspend isn't recommended .
Why?
It seems that some threads is still working even after the close of the windows, Why this happens? How can i fix it?
Is another method of killing a thread exist in wpf?
1) Why?
Suspend method has been marked as Obsolete by Microsoft. Error states itself:
Thread.Suspend has been deprecated. Please use other classes in
System.Threading, such as Monitor, Mutex, Event, and Semaphore, to
synchronize Threads or protect resources.
2) It seems that some threads is still working even after the close of
the windows, Why this happens? How can i fix it?
You have started all threads as foreground thread which won't stop automatically when main thread finishes its execution. In case you want to stop all threads once all foreground threads stops, you should mark thread as background thread.
windowThread.IsBackground = true;
3) Is another method of killing a thread exist in wpf?
Use Thread.Abort(). However, closing your main thread will automatically stop all background threads (IsBackground set to true on thread), you should not worry about killing them.
What are you trying to do? You are creating threads just for the purpose of checking some condition? And when the condition is true, you change the visibility and block all threads(!) from further execution. And when the condition is not true, you create another thread that does the same. Why are you suspending all threads (including the active one) instead of just letting it terminate? And if you want to periodically check for a condition, use a timer or a wait event instead.
Just as a side note: Your foreach-loops will eventually throw InvalidOperationException, because you're changing the collection without a lock.
And then, don't try to kill threads. Use flags or signals instead. Any attempt to kill threads is a) bad design and b) prone to errors and unexpected behavior.

When creating a new thread, changes to GUI are not being made (C#)

With some help I have managed to create a new thread, although the method appears to execute, the conditions of the method either make a green or red light appear, although when running the method (Check1..etc) without the new thread the changes are reflected on the GUI (e.g. Red / Green Light Appears), but when creating a new thread and running the method the changes are not reflected on the Form / GUI.
// Method / Action to start the checks private void StartChecks_Click(object sender, EventArgs e)
{
Thread t = new Thread(
o =>
{
InitChecks();
});
t.Start();
}
// Check1 public void Check1()
{
// lets grabs the info from the config!
var lines = File.ReadAllLines("probe_settings.ini");
var dictionary = lines.Zip(lines.Skip(1), (a, b) => new { Key = a, Value = b })
.Where(l => l.Key.StartsWith("#"))
.ToDictionary(l => l.Key, l => l.Value);
// lets set the appropriate value for this check field
label1.Text = dictionary["#CheckName1"];
// lets define variables and convert the string in the dictionary to int for the sock.connection method!
int portno1;
int.TryParse(dictionary["#PortNo1"], out portno1);
// Convert hostname to IP, performance issue when using an invalid port on a hostname using the TcpClient class!
IPAddress[] addresslist = Dns.GetHostAddresses(hostname2);
foreach (IPAddress theaddress in addresslist)
{
// Attempt to create socket and connect to specified port on host
TcpClient tcP = new System.Net.Sockets.TcpClient();
try
{
tcP.ReceiveTimeout = 1;
tcP.SendTimeout = 1;
tcP.Connect(theaddress, portno1);
displayGreen1();
tcP.Close();
}
catch
{
displayRed1();
}
}
}
// Change the lights when the condition is met
public void displayGreen1()
{
pictureBox2.Visible = false;
pictureBox1.Visible = true;
}
private void displayRed1()
{
pictureBox2.Visible = true;
pictureBox1.Visible = false;
}
This is how WinForms is designed. You can't make changes from another thread.
the solution usually is to use asynchronous delegate.
First of all add this declaration
public delegate void MyDelegate1 ();
public delegate void MyDelegate2 ();
Then When you are in another thread You should do:
MyDelegate1 d1= new MyDelegate1 (displayGreen1);
this.BeginInvoke(d1);
MyDelegate2 d2= new MyDelegate2 (displayRed1);
this.BeginInvoke(d2);
This is happening because UI controls can only be updated from the UI thread. When you do not create a new thread, the code which updates the controls runs on the UI thread, so it works as you expect. When you do create a new thread, because this thread is not the UI thread, the code which is supposed to update the controls fails to do so.
You can ensure that the code which updates the controls runs on the UI thread by changing the method calls to:-
this.BeginInvoke(new Action(() => displayRed1()));
and
this.BeginInvoke(new Action(() => displayGreen1()));
Incidentally (unrelated to your current problem):-
Try to avoid creating an explicit thread. Instead use the thread pool to manage the thread for you, e.g. ThreadPool.QueueUserWorkItem(x => InitChecks()). (Note that this will still run on a non-UI thread so you still need to use BeginInvoke() as detailed above.). The thread pool knows best about when to create and execute a thread and using it will, ultimately, make your code more efficient.
Try to avoid catching all exception types in your try{...}catch{...}. This is stating that your code knows what to do when any type of exception is thrown. Instead, only catch exceptions which you know exactly how to handle,
e.g.
try
{
...
}
catch(TcpException)
{
...
}
catch(AnotherKnownException)
{
...
}
...
Note that it is OK to also have a catch block for all exception types as long as you rethrow the exception when exiting the block,
e.g.
try
{
...
}
catch(KnownException)
{
...
}
catch(Exception)
{
// perform some logging, rollback, etc.
throw;
}
At your skill level, it would be best to:
use timer in the form to check some status variable (say bool _pb1Visible and bool _pb2Visible)
in the timer event update picturebox visibility
in the thread, update ONLY bool member variables mentioned above.
It will work like a charm!
Simple example:
In your Check1() method, instead of:
displayGreen1();
put
_pb1Visible=true;
_pb1Visible=false;
and instead of
displayRed1();
put
_pb1Visible=false;
_pb1Visible=true;
Put the timer on the form. In the timer event, do the:
pictureBox2.Visible = _pb2Visible;
pictureBox1.Visible = _pb1Visible;

Implementing a thread queue/wait, how?

I have a timer calling a function every 15 minutes, this function counts the amount of lines in my DGV and starts a thread for each lines (of yet another function), said thread parse a web page which can take anywhere from 1 second to 10 second to finish.
Whilst it does work fine as it is with 1-6 rows, anymore will cause the requests to time-out.
I want it to wait for the newly created thread to finish processing before getting back in the loop to create another thread without locking the main UI
for (int x = 0; x <= dataGridFollow.Rows.Count - 1; x++)
{
string getID = dataGridFollow.Rows[x].Cells["ID"].Value.ToString();
int ID = int.Parse(getID);
Thread t = new Thread(new ParameterizedThreadStart(UpdateLo));
t.Start(ID);
// <- Wait for thread to finish here before getting back in the for loop
}
I have googled a lot in the past 24 hours, read a lot about this specific issue and its implementations (Thread.Join, ThreadPools, Queuing, and even SmartThreadPool).
It's likely that I've read the correct answer somewhere but I'm not at ease enough with C# to decypher those Threading tools
Thanks for your time
to avoid the UI freeze the framework provide a class expressly for these purposes: have a look at the BackgroundWorker class (executes an operation on a separate thread), here's some infos : http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
http://msdn.microsoft.com/en-us/magazine/cc300429.aspx
Btw looks if I understand correctly you don't want to parallelize any operation so just wait for the method parsing the page to be completed. Basically for each (foreach look) row of your grid you get the id and call the method. If you want to go parallel just reuse the same foreach loop and add make it Parallel
http://msdn.microsoft.com/en-us/library/dd460720.aspx
What you want is to set off a few workers that do some task.
When one finishes you can start a new one off.
I'm sure there is a better way using thread pools or whatever.. but I was bored so i came up with this.
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using System.Threading;
namespace WorkerTest
{
class Program
{
static void Main(string[] args)
{
WorkerGroup workerGroup = new WorkerGroup();
Console.WriteLine("Starting...");
for (int i = 0; i < 100; i++)
{
var work = new Action(() =>
{
Thread.Sleep(1000); //somework
});
workerGroup.AddWork(work);
}
while (workerGroup.WorkCount > 0)
{
Console.WriteLine(workerGroup.WorkCount);
Thread.Sleep(1000);
}
Console.WriteLine("Fin");
Console.ReadLine();
}
}
public class WorkerGroup
{
private List<Worker> workers;
private Queue<Action> workToDo;
private object Lock = new object();
public int WorkCount { get { return workToDo.Count; } }
public WorkerGroup()
{
workers = new List<Worker>();
workers.Add(new Worker());
workers.Add(new Worker());
foreach (var w in workers)
{
w.WorkCompleted += (OnWorkCompleted);
}
workToDo = new Queue<Action>();
}
private void OnWorkCompleted(object sender, EventArgs e)
{
FindWork();
}
public void AddWork(Action work)
{
workToDo.Enqueue(work);
FindWork();
}
private void FindWork()
{
lock (Lock)
{
if (workToDo.Count > 0)
{
var availableWorker = workers.FirstOrDefault(x => !x.IsBusy);
if (availableWorker != null)
{
var work = workToDo.Dequeue();
availableWorker.StartWork(work);
}
}
}
}
}
public class Worker
{
private BackgroundWorker worker;
private Action work;
public bool IsBusy { get { return worker.IsBusy; } }
public event EventHandler WorkCompleted;
public Worker()
{
worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(OnWorkerDoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OnWorkerRunWorkerCompleted);
}
private void OnWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (WorkCompleted != null)
{
WorkCompleted(this, EventArgs.Empty);
}
}
public void StartWork(Action work)
{
if (!IsBusy)
{
this.work = work;
worker.RunWorkerAsync();
}
else
{
throw new InvalidOperationException("Worker is busy");
}
}
private void OnWorkerDoWork(object sender, DoWorkEventArgs e)
{
work.Invoke();
work = null;
}
}
}
This would be just a starting point.
You could start it off with a list of Actions and then have a completed event for when that group of actions is finished.
then at least you can use a ManualResetEvent to wait for the completed event.. or whatever logic you want really.
Call a method directly or do a while loop (with sleep calls) to check the status of the thread.
There are also async events but the would call another method, and you want to continue from the same point.
I have no idea why the requests would timeout. That sounds like a different issue. However, I can make a few suggestions regarding your current approach.
Avoid creating threads in loops with nondeterministic bounds. There is a lot of overhead in creating threads. If the number of operations is not known before hand then use the ThreadPool or the Task Parallel Library instead.
You are not going to get the behavior you want by blocking the UI thread with Thread.Join. The cause the UI to become unresponsive and it will effectively serialize the operations and cancel out any advantage you were hoping to gain with threads.
If you really want to limit the number of concurrent operations then a better solution is to create a separate dedicated thread for kicking off the operations. This thread will spin around a loop indefinitely waiting for items to appear in a queue and when they do it will dequeue them and use that information to kick off an operation asynchronously (again using the ThreadPool or TPL). The dequeueing thread can contain the logic for limiting the number of concurrent operations. Search for information regarding the producer-consumer pattern to get a better understand of how you can implement this.
There is a bit of a learning curve, but who said threading was easy right?
If I understand correctly, what you're currently doing is looping through a list of IDs in the UI thread, starting a new thread to handle each one. The blocking issue you're seeing then could well be that it's taking too many resources to create unique threads. So, personally (without knowing more) would redesign the process like so:
//Somewhere in the UI Thread
Thread worker = new Thread(new ParameterizedThreadStart(UpdateLoWorker));
worker.Start(dataGridFollow.Rows);
//worker thread
private void UpdateLoWorker(DataRowCollection rows)
{
foreach(DataRow r in rows){
string getID = r.Cells["ID"].Value.ToString();
int ID = int.Parse(getID);
UpdateLo(ID);
}
}
Here you'd have a single non-blocking worker which sequentially handles each ID.
Consider using Asynchronous CTP. It's an asynch pattern Microsoft recently released for download. It should simplify asynch programming tremendouesly. The link is http://msdn.microsoft.com/en-us/vstudio/async.aspx. (Read the whitepaper first)
Your code would look something like the following. (I've not verified my syntax yet, sorry).
private async Task DoTheWork()
{
for(int x = 0; x <= dataGridFollow.Rows.Count - 1; x++)
{
string getID = dataGridFollow.Rows[x].Cells["ID"].Value.ToString();
int ID = int.Parse(getID);
task t = new Task(new Action<object>(UpdateLo), ID);
t.Start();
await t;
}
}
This method returns a Task that can be checked periodically for completion. This follows the pattern of "fire and forget" meaning you just call it and presumably, you don't care when it completes (as long as it does complete before 15 minutes).
EDIT
I corrected the syntax above, you would need to change UpdateLo to take an object instead of an Int.
For a simple background thread runner that will run one thread from a queue at a time you can do something like this:
private List<Thread> mThreads = new List<Thread>();
public static void Main()
{
Thread t = new Thread(ThreadMonitor);
t.IsBackground = true;
t.Start();
}
private static void ThreadMonitor()
{
while (true)
{
foreach (Thread t in mThreads.ToArray())
{
// Runs one thread in the queue and waits for it to finish
t.Start();
mThreads.Remove(t);
t.Join();
}
Thread.Sleep(2000); // Wait before checking for new threads
}
}
// Called from the UI or elsewhere to create any number of new threads to run
public static void DoStuff()
{
Thread t = new Thread(DoCorestuff);
t.IsBackground = true;
mActiveThreads.Add(t);
}
public static void DoStuffCore()
{
// Your code here
}

Categories

Resources