background/Asynchronous process using Threading or Delegate - c#

At My website
1. After filling form Inserting that record in SQL database
2. In Next Line I take some class object then send to Matching with other record
3. In matching application taking so much time
Now I have decided I will put matching process in background/Asynchronous by using Threading or Delegate
My Previous code was:
1. Inserting all information in database
objclsBbDAL.InsertAcquirePrvider(objAcqProvBL);
2. Matching related record with other record in database
clsMatchMakingDAL objclsMatchMakingDAL = new clsMatchMakingDAL();
objclsMatchMakingDAL.AcquireMatch(objAcqProvBL);
Q 1. Which one is best way to run process in background/Asynchronous - Threading or Delegate
Now I am using Threading:
objclsBbDAL.InsertAcquirePrvider(objAcqProvBL);
//Threading
CallMatchMakingOnDiffThread(objAcqProvBL);
private void CallMatchMakingOnDiffThread(clsAcquireProviderBL objAcqPro)
{
clsMatchMakingDAL objclsMatchMakingDAL = new clsMatchMakingDAL();
Thread objThread = new Thread(() => objclsMatchMakingDAL.AcquireMatch(objAcqPro));
objThread.Start();
}
Q2. How can do this task with Delegate?

Delegates are like callbacks, you use them to notify that an asynchronous task has been completed, meaning the thread needs to call an event, which should have a delegate hooked onto it.
For example:
public struct ThreadData
{
public int handle;
public string details;
public ThreadData(int handle, string details)
{
this.handle = handle;
this.details = details;
}
}
public class ThreadWorker
{
private List<Thread> threads = new List<Thread>();
public int BeginAsyncWork(string details)
{
Thread thread = new Thread(new ParameterizedThreadStart(ThreadMethod));
threads.Add(thread);
thread.Start(new ThreadData(threads.Count - 1, details));
return threads.Count - 1;
}
private void ThreadMethod(object parameter)
{
ThreadData data = (ThreadData)parameter;
Console.WriteLine(data.details);
if (ThreadFinished != null) { ThreadFinished(data.handle); }
}
public delegate void ThreadEndDelegate(int handle);
public event ThreadEndDelegate ThreadFinished;
}
public static class Program
{
private static int[] handles;
public static void Main()
{
handles = new int[4];
ThreadWorker worker = new ThreadWorker();
worker.ThreadFinished += new ThreadWorker.ThreadEndDelegate(OnThreadFinished);
for (int i = 0; i < 4; i++)
{
handles[i] = worker.BeginAsyncWork("working: " + i);
}
Console.ReadKey();
}
private static void OnThreadFinished(int handle)
{
Console.WriteLine("thread: " + handle + " finished");
handles[handle] = 0;
}
}
It's long winded but it allows for full control over your threads.
EDIT:
Untested code. The shortest possible solution I could think of.
objclsBbDAL.InsertAcquirePrvider(objAcqProvBL);
//Threading
CallMatchMakingOnDiffThread(objAcqProvBL);
private void OnMatchAcquired(object match)
{
//do work with found match
}
private event Action<object> MatchAcquired = new Action<object>(OnMatchAcquired);
private void CallMatchMakingOnDiffThread(clsAcquireProviderBL objAcqPro)
{
clsMatchMakingDAL objclsMatchMakingDAL = new clsMatchMakingDAL();
Thread objThread = new Thread(
() => object match = (object)objclsMatchMakingDAL.AcquireMatch(objAcqPro); if(ThreadComplete!=nil){MatchAcquired(match);}
);
objThread.Start();
}

You can not do background processing with only a delegate.
A delegate is totally different from a thread or an asynchronous process.
You can understand a delegate as a pointer to a function.
Threads use delegates to execute a certain function but delegates alone are not any kind of background execution.
Doing what you mentioned up-there would run the process in background, but you have to know the costs for running the operation in background and in this way. You also need to know if it does really needs to be run in background or it only needs optimization.

The easyest way (for me at least) is to use a delegate and BeginInvoke, which will return immediately and for which you can supply a callback that is executed when the delegate is finished.
More info on MSDN.
In your sample code I do not see, that you need to be notified, when the operation is finished so you could do something like this:
new Action(() =>
{
clsMatchMakingDAL objclsMatchMakingDAL = new clsMatchMakingDAL();
objclsMatchMakingDAL.AcquireMatch(objAcqPro);
}).BeginInvoke(null, null);
This would execute the matching functionality on another thread that is managed by .Net for you. If you need to be notified on completion, then the first argument to the BeginInvoke call could be another delegate to handle the completion event.

Related

Multiple events and multi threading

I have a service that raises multiple events, some of them can be raised at the same time. I need to process those events and run a potentially long running method based on the event arguments.
What I did is to create a BlockingCollection<T> that will store the events an a Task that will keep taking one event at a time until it will be signaled to stop using a CancellationTokenSource.
My concern is that I'm not handling the synchronization good enough.
This is the class that handles everything (it's used as a WPF ViewModel):
public class EventsTest
{
//private fields
private BlockingCollection<IoEventArgs> _queue;
private CancellationTokenSource _tokenSource;
private IoService _ioService;
private Task _workerTask;
private static EventWaitHandle _eventWaiter;
public EventsTest()
{
_queue = new BlockingCollection<IoEventArgs>();
_tokenSource = new CancellationTokenSource();
_eventWaiter = new EventWaitHandle(false, EventResetMode.AutoReset);
//this is the object that raises multiple events
_ioService = new IoService();
_ioService.IoEvent += _ioService_IoEvent;
//Start Listening
var t = Task.Factory.StartNew(StartListening, _tokenSource, TaskCreationOptions.LongRunning);
}
//IO events listener
private void _ioService_IoEvent(string desc, int portNum)
{
//add events to a blocking collection
_queue.Add(new IoEventArgs() { Description = desc, PortNum = portNum });
}
private void StartListening(object dummy)
{
//process the events one at a time
while (!_tokenSource.IsCancellationRequested)
{
var eve = _queue.Take();
switch (eve.PortNum)
{
case 0:
LongRunningMethod(eve.Description);
break;
case 1:
//invoke a long running method
break;
default:
break;
}
}
}
//sample long running method
private void LongRunningMethod(string data)
{
_eventWaiter.WaitOne(10000);
}
}
How can I make this process more robust in terms of thread safety?
Will adding a lock around each method implementation improve the safety of the process?
Your .Take() won't be canceled so you might wait forever there.
You could pass the token on:
var eve = _queue.Take(_tokenSource);
but then you would have to handle the exception.
A better approach would be the TryTake(out eve, 1000, _tokenSource) and steer with the returned boolean.
Or forget about the CancellationToken and just use AddingComplete()
This sounds like a situation where Microsoft's Reactive Framework is a far better fit.
Your code would look like this:
public class EventsTest
{
private IDisposable _subscription;
public EventsTest()
{
IoService ioService = new IoService();
_subscription =
Observable
.FromEvent<IoEvent, IoEventArgs>(
a => ioService.IoEvent += a, a => ioService.IoEvent -= a)
.Subscribe(eve =>
{
switch (eve.PortNum)
{
case 0:
LongRunningMethod(eve.Description);
break;
case 1:
//invoke a long running method
break;
default:
break;
}
});
}
private void LongRunningMethod(string data)
{
}
}
This should automatically ensure multiple events are queued and will never overlap. If there's problem just drop a .Synchronize() call in before the .Subscribe(...) and then it'll work perfectly.
When you want to cancel the event just call _subscription.Dispose() and it will all be cleaned up for you.
NuGet "Rx-Main" to get the bits you need.

How to update UI from another thread running in another class

I am currently writing my first program on C# and I am extremely new to the language (used to only work with C so far). I have done a lot of research, but all answers were too general and I simply couldn't get it t work.
So here my (very common) problem:
I have a WPF application which takes inputs from a few textboxes filled by the user and then uses that to do a lot of calculations with them. They should take around 2-3 minutes, so I would like to update a progress bar and a textblock telling me what the current status is.
Also I need to store the UI inputs from the user and give them to the thread, so I have a third class, which I use to create an object and would like to pass this object to the background thread.
Obviously I would run the calculations in another thread, so the UI doesn't freeze, but I don't know how to update the UI, since all the calculation methods are part of another class.
After a lot of reasearch I think the best method to go with would be using dispatchers and TPL and not a backgroundworker, but honestly I am not sure how they work and after around 20 hours of trial and error with other answers, I decided to ask a question myself.
Here a very simple structure of my program:
public partial class MainWindow : Window
{
public MainWindow()
{
Initialize Component();
}
private void startCalc(object sender, RoutedEventArgs e)
{
inputValues input = new inputValues();
calcClass calculations = new calcClass();
try
{
input.pota = Convert.ToDouble(aVar.Text);
input.potb = Convert.ToDouble(bVar.Text);
input.potc = Convert.ToDouble(cVar.Text);
input.potd = Convert.ToDouble(dVar.Text);
input.potf = Convert.ToDouble(fVar.Text);
input.potA = Convert.ToDouble(AVar.Text);
input.potB = Convert.ToDouble(BVar.Text);
input.initStart = Convert.ToDouble(initStart.Text);
input.initEnd = Convert.ToDouble(initEnd.Text);
input.inita = Convert.ToDouble(inita.Text);
input.initb = Convert.ToDouble(initb.Text);
input.initc = Convert.ToDouble(initb.Text);
}
catch
{
MessageBox.Show("Some input values are not of the expected Type.", "Wrong Input", MessageBoxButton.OK, MessageBoxImage.Error);
}
Thread calcthread = new Thread(new ParameterizedThreadStart(calculations.testMethod);
calcthread.Start(input);
}
public class inputValues
{
public double pota, potb, potc, potd, potf, potA, potB;
public double initStart, initEnd, inita, initb, initc;
}
public class calcClass
{
public void testmethod(inputValues input)
{
Thread.CurrentThread.Priority = ThreadPriority.Lowest;
int i;
//the input object will be used somehow, but that doesn't matter for my problem
for (i = 0; i < 1000; i++)
{
Thread.Sleep(10);
}
}
}
I would be very grateful if someone had a simple explanation how to update the UI from inside the testmethod. Since I am new to C# and object oriented programming, too complicated answers I will very likely not understand, I'll do my best though.
Also if someone has a better idea in general (maybe using backgroundworker or anything else) I am open to see it.
First you need to use Dispatcher.Invoke to change the UI from another thread and to do that from another class, you can use events.
Then you can register to that event(s) in the main class and Dispatch the changes to the UI and in the calculation class you throw the event when you want to notify the UI:
class MainWindow : Window
{
private void startCalc()
{
//your code
CalcClass calc = new CalcClass();
calc.ProgressUpdate += (s, e) => {
Dispatcher.Invoke((Action)delegate() { /* update UI */ });
};
Thread calcthread = new Thread(new ParameterizedThreadStart(calc.testMethod));
calcthread.Start(input);
}
}
class CalcClass
{
public event EventHandler ProgressUpdate;
public void testMethod(object input)
{
//part 1
if(ProgressUpdate != null)
ProgressUpdate(this, new YourEventArgs(status));
//part 2
}
}
UPDATE:
As it seems this is still an often visited question and answer I want to update this answer with how I would do it now (with .NET 4.5) - this is a little longer as I will show some different possibilities:
class MainWindow : Window
{
Task calcTask = null;
void buttonStartCalc_Clicked(object sender, EventArgs e) { StartCalc(); } // #1
async void buttonDoCalc_Clicked(object sender, EventArgs e) // #2
{
await CalcAsync(); // #2
}
void StartCalc()
{
var calc = PrepareCalc();
calcTask = Task.Run(() => calc.TestMethod(input)); // #3
}
Task CalcAsync()
{
var calc = PrepareCalc();
return Task.Run(() => calc.TestMethod(input)); // #4
}
CalcClass PrepareCalc()
{
//your code
var calc = new CalcClass();
calc.ProgressUpdate += (s, e) => Dispatcher.Invoke((Action)delegate()
{
// update UI
});
return calc;
}
}
class CalcClass
{
public event EventHandler<EventArgs<YourStatus>> ProgressUpdate; // #5
public TestMethod(InputValues input)
{
//part 1
ProgressUpdate.Raise(this, status); // #6 - status is of type YourStatus
// alternative version to the extension for C# 6+:
ProgressUpdate?.Invoke(this, new EventArgs<YourStatus>(status));
//part 2
}
}
static class EventExtensions
{
public static void Raise<T>(this EventHandler<EventArgs<T>> theEvent,
object sender, T args)
{
if (theEvent != null)
theEvent(sender, new EventArgs<T>(args));
}
}
#1) How to start the "synchronous" calculations and run them in the background
#2) How to start it "asynchronous" and "await it": Here the calculation is executed and completed before the method returns, but because of the async/await the UI is not blocked (BTW: such event handlers are the only valid usages of async void as the event handler must return void - use async Task in all other cases)
#3) Instead of a new Thread we now use a Task. To later be able to check its (successfull) completion we save it in the global calcTask member. In the background this also starts a new thread and runs the action there, but it is much easier to handle and has some other benefits.
#4) Here we also start the action, but this time we return the task, so the "async event handler" can "await it". We could also create async Task CalcAsync() and then await Task.Run(() => calc.TestMethod(input)).ConfigureAwait(false); (FYI: the ConfigureAwait(false) is to avoid deadlocks, you should read up on this if you use async/await as it would be to much to explain here) which would result in the same workflow, but as the Task.Run is the only "awaitable operation" and is the last one we can simply return the task and save one context switch, which saves some execution time.
#5) Here I now use a "strongly typed generic event" so we can pass and receive our "status object" easily
#6) Here I use the extension defined below, which (aside from ease of use) solve the possible race condition in the old example. There it could have happened that the event got null after the if-check, but before the call if the event handler was removed in another thread at just that moment. This can't happen here, as the extensions gets a "copy" of the event delegate and in the same situation the handler is still registered inside the Raise method.
I am going to throw you a curve ball here. If I have said it once I have said it a hundred times. Marshaling operations like Invoke or BeginInvoke are not always the best methods for updating the UI with worker thread progress.
In this case it usually works better to have the worker thread publish its progress information to a shared data structure that the UI thread then polls at regular intervals. This has several advantages.
It breaks the tight coupling between the UI and worker thread that Invoke imposes.
The UI thread gets to dictate when the UI controls get updated...the way it should be anyway when you really think about it.
There is no risk of overrunning the UI message queue as would be the case if BeginInvoke were used from the worker thread.
The worker thread does not have to wait for a response from the UI thread as would be the case with Invoke.
You get more throughput on both the UI and worker threads.
Invoke and BeginInvoke are expensive operations.
So in your calcClass create a data structure that will hold the progress information.
public class calcClass
{
private double percentComplete = 0;
public double PercentComplete
{
get
{
// Do a thread-safe read here.
return Interlocked.CompareExchange(ref percentComplete, 0, 0);
}
}
public testMethod(object input)
{
int count = 1000;
for (int i = 0; i < count; i++)
{
Thread.Sleep(10);
double newvalue = ((double)i + 1) / (double)count;
Interlocked.Exchange(ref percentComplete, newvalue);
}
}
}
Then in your MainWindow class use a DispatcherTimer to periodically poll the progress information. Configure the DispatcherTimer to raise the Tick event on whatever interval is most appropriate for your situation.
public partial class MainWindow : Window
{
public void YourDispatcherTimer_Tick(object sender, EventArgs args)
{
YourProgressBar.Value = calculation.PercentComplete;
}
}
You're right that you should use the Dispatcher to update controls on the UI thread, and also right that long-running processes should not run on the UI thread. Even if you run the long-running process asynchronously on the UI thread, it can still cause performance issues.
It should be noted that Dispatcher.CurrentDispatcher will return the dispatcher for the current thread, not necessarily the UI thread. I think you can use Application.Current.Dispatcher to get a reference to the UI thread's dispatcher if that's available to you, but if not you'll have to pass the UI dispatcher in to your background thread.
Typically I use the Task Parallel Library for threading operations instead of a BackgroundWorker. I just find it easier to use.
For example,
Task.Factory.StartNew(() =>
SomeObject.RunLongProcess(someDataObject));
where
void RunLongProcess(SomeViewModel someDataObject)
{
for (int i = 0; i <= 1000; i++)
{
Thread.Sleep(10);
// Update every 10 executions
if (i % 10 == 0)
{
// Send message to UI thread
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Normal,
(Action)(() => someDataObject.ProgressValue = (i / 1000)));
}
}
}
Everything that interacts with the UI must be called in the UI thread (unless it is a frozen object). To do that, you can use the dispatcher.
var disp = /* Get the UI dispatcher, each WPF object has a dispatcher which you can query*/
disp.BeginInvoke(DispatcherPriority.Normal,
(Action)(() => /*Do your UI Stuff here*/));
I use BeginInvoke here, usually a backgroundworker doesn't need to wait that the UI updates. If you want to wait, you can use Invoke. But you should be careful not to call BeginInvoke to fast to often, this can get really nasty.
By the way, The BackgroundWorker class helps with this kind of taks. It allows Reporting changes, like a percentage and dispatches this automatically from the Background thread into the ui thread. For the most thread <> update ui tasks the BackgroundWorker is a great tool.
If this is a long calculation then I would go background worker. It has progress support. It also has support for cancel.
http://msdn.microsoft.com/en-us/library/cc221403(v=VS.95).aspx
Here I have a TextBox bound to contents.
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Debug.Write("backgroundWorker_RunWorkerCompleted");
if (e.Cancelled)
{
contents = "Cancelled get contents.";
NotifyPropertyChanged("Contents");
}
else if (e.Error != null)
{
contents = "An Error Occured in get contents";
NotifyPropertyChanged("Contents");
}
else
{
contents = (string)e.Result;
if (contentTabSelectd) NotifyPropertyChanged("Contents");
}
}
You are going to have to come back to your main thread (also called UI thread) in order to update the UI.
Any other thread trying to update your UI will just cause exceptions to be thrown all over the place.
So because you are in WPF, you can use the Dispatcher and more specifically a beginInvoke on this dispatcher. This will allow you to execute what needs done (typically Update the UI) in the UI thread.
You migh also want to "register" the UI in your business, by maintaining a reference to a control/form, so you can use its dispatcher.
Thank God, Microsoft got that figured out in WPF :)
Every Control, like a progress bar, button, form, etc. has a Dispatcher on it. You can give the Dispatcher an Action that needs to be performed, and it will automatically call it on the correct thread (an Action is like a function delegate).
You can find an example here.
Of course, you'll have to have the control accessible from other classes, e.g. by making it public and handing a reference to the Window to your other class, or maybe by passing a reference only to the progress bar.
Felt the need to add this better answer, as nothing except BackgroundWorker seemed to help me, and the answer dealing with that thus far was woefully incomplete. This is how you would update a XAML page called MainWindow that has an Image tag like this:
<Image Name="imgNtwkInd" Source="Images/network_on.jpg" Width="50" />
with a BackgroundWorker process to show if you are connected to the network or not:
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
public partial class MainWindow : Window
{
private BackgroundWorker bw = new BackgroundWorker();
public MainWindow()
{
InitializeComponent();
// Set up background worker to allow progress reporting and cancellation
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
// This is your main work process that records progress
bw.DoWork += new DoWorkEventHandler(SomeClass.DoWork);
// This will update your page based on that progress
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
// This starts your background worker and "DoWork()"
bw.RunWorkerAsync();
// When this page closes, this will run and cancel your background worker
this.Closing += new CancelEventHandler(Page_Unload);
}
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
BitmapImage bImg = new BitmapImage();
bool connected = false;
string response = e.ProgressPercentage.ToString(); // will either be 1 or 0 for true/false -- this is the result recorded in DoWork()
if (response == "1")
connected = true;
// Do something with the result we got
if (!connected)
{
bImg.BeginInit();
bImg.UriSource = new Uri("Images/network_off.jpg", UriKind.Relative);
bImg.EndInit();
imgNtwkInd.Source = bImg;
}
else
{
bImg.BeginInit();
bImg.UriSource = new Uri("Images/network_on.jpg", UriKind.Relative);
bImg.EndInit();
imgNtwkInd.Source = bImg;
}
}
private void Page_Unload(object sender, CancelEventArgs e)
{
bw.CancelAsync(); // stops the background worker when unloading the page
}
}
public class SomeClass
{
public static bool connected = false;
public void DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bw = sender as BackgroundWorker;
int i = 0;
do
{
connected = CheckConn(); // do some task and get the result
if (bw.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
Thread.Sleep(1000);
// Record your result here
if (connected)
bw.ReportProgress(1);
else
bw.ReportProgress(0);
}
}
while (i == 0);
}
private static bool CheckConn()
{
bool conn = false;
Ping png = new Ping();
string host = "SomeComputerNameHere";
try
{
PingReply pngReply = png.Send(host);
if (pngReply.Status == IPStatus.Success)
conn = true;
}
catch (PingException ex)
{
// write exception to log
}
return conn;
}
}
For more information: https://msdn.microsoft.com/en-us/library/cc221403(v=VS.95).aspx

Updating progress bar from a threadpool c#

I have trying to process some data using multithreading where I am using threadpool to generate threads equal to the number of cores(Limited to .NET 2.0 to 3.5 so cant use TPL).
All my threads execute the same function operating in different parts of my data.
My problem is I am unable to update the progress bar from the threads of the threadpool. Found solutions such as invoke and Background worker but could not really understand how to use them please help me out how to use them.
my code looks like
private static float[] inpdat=new float[1000];//The input array to process
//The spawned threads
public void dowork(object o)
{
int np = (int)o;
for(int i=np;i<inpdat.length;i=i+Environment.ProcessorCount)
{
//do some processing
if(np==0)
{
//update progress bar here
}
}
}
//The main thread
for (int npou = 0; npou < numproc; npou++)
{
resetEvents[npou] = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(new WaitCallback(dowork), npou);
PetrelLogger.InfoOutputWindow("manual reset event set");
}
Speed is of paramount importance to me so would be very helpful if the cross thread calling takes up minimum time.
Thanks
Here is an example:
ThreadPool.QueueUserWorkItem(new WaitCallback(o =>
{
// worker method implementation
.....
progressBar1.Invoke(new MethodInvoker(() => progressBar1.Value = 20));
}));
There is a little you can do with updating user controls, in your case Progress bar.
Add your form as the input parameter, or add some callback interface for the results, that your form will implement:
interface IMyCallback
{
void Progress(int progress);
}
In form implementation add following code:
void Progress(int Progress)
{
if(this.InvokeRequired)
{
this.BeginInvoke(new ParametrizedThreadStart(Inv_Progress), Progress);
}
else
{
Inv_Progress(Progress);
}
}
void Inv_Progress(object obj)
{
int progress = obj as int;
// do your update progress bar work here
}
Now you can do following:
public void dowork(object o)
{
int np = (int)o;
for(int i=np;i<inpdat.length;i=i+Environment.ProcessorCount)
{
//do some processing
if(np==0)
{
myCallback.Progress(0);
}
}
}
A standard invoke is probably easiest, and you can use an anonymous delegate to make it cleaner.
int n = 5;
myProgressBar.Invoke(
delegate
{
myProgressBar.Value = n;
}
);
Keep in mind that in certain scenarios (e.g. looped use of this delegate from within one thread) you may need to declare a delegate and pass the value into it as a parameter. If you don't, you can get strange behaviour with locals. This is the case for use of anonymous methods and the Action class, too.

How to execute method calls of a custom class in a separate thread?

I have an UI, a custom class, and a thread. I want to run the custom class completely in a separate thread. Is there a clean way of doing this?
For example. On the MainForm below, when UI calls _threadOneClass.Sleep, I need the UI to go to the spawned ThreadOne and invoke the Sleep method in ThreadOne, not in the main thread.
Basically, all method calls in MyClass need to be executed in ThreadOne, not in main thread. It is like, the MyClass runs on its own "process", while still visible to be called from MainForm.
The MainForm has 3 buttons, and 1 textbox for logging.
I was thinking of deriving the Thread class, but it is sealed. So deriving is definitely a wrong way per Microsoft.
Help dear experts?
Here is the output (MainThread ID=10, ThreadOne ID=11)
MyClass instantiated
Starting ThreadOne
11-Run.start
Sleeping ThreadOne
10-Run.sleep for 3000 'Need this to run on ThreadID 11
10-Run.woke up 'Need this to run on ThreadID 11
Stopping ThreadOne
11-Run.done
Here is how the code look like.
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private Thread _threadOneThread;
private MyClass _threadOneClass;
private void btnThreadOneCreate_Click(object sender, EventArgs e)
{
_threadOneClass = new MyClass(this);
_threadOneThread = new Thread(new ThreadStart(_threadOneClass.Run));
_threadOneThread.Start();
}
private void btnThreadOneStop_Click(object sender, EventArgs e)
{
_threadOneClass.IsRunning = false;
}
private void btnThreadOneSleep_Click(object sender, EventArgs e)
{
_threadOneClass.Sleep(3000);
}
public void Log(string txt)
{
MainForm.SetText(txtLog, txt);
}
internal static void SetText(Control ctl, string val)
{
if (ctl.InvokeRequired)
ctl.Invoke((MethodInvoker)delegate() { ctl.Text += Environment.NewLine + val; });
else
ctl.Text += Environment.NewLine + val;
}
}
class MyClass
{
public MyClass(MainForm frm)
{
_mainForm = frm;
}
private MainForm _mainForm;
public bool IsRunning = true;
public void Run()
{
_mainForm.Log(Thread.CurrentThread.ManagedThreadId.ToString() + "-Run.start");
while (IsRunning) { }
_mainForm.Log(Thread.CurrentThread.ManagedThreadId.ToString() + "-Run.done");
}
public void Sleep(int milliseconds)
{
_mainForm.Log(Thread.CurrentThread.ManagedThreadId.ToString() + "-Run.sleep for " + milliseconds.ToString());
Thread.Sleep(milliseconds);
_mainForm.Log(Thread.CurrentThread.ManagedThreadId.ToString() + "-Run.woke up");
}
}
Threads allow you to run heavy operations while you continue doing other things. In the case of user interfaces (your scenario), asynchronous behavior is almost always necessary as blocking the UI thread will cause to be unresponsive to the user and just isn't an option.
Luckily, the folks at Microsoft has made it extremely easy to write the same code, but in an asynchronous manner. I usually use Tasks because I like the control you get over the operation as well as the ContinueWith() lets you control what you do with the result should you need to propagate data back to the calling thread. If you prefer to use threads, ThreadPool.QueueUserWorkItem is just as easy.
Any operation you do not want to block the UI thread wrap it like this,
Task.Factory.StartNew(() => Object.PerformOperation());
or
ThreadPool.QueueUserWorkItem(new WaitCallback((x) => Object.PeroformOperation()));
I find this allows me to write the same exact code, but without blocking the UI thread. If you have several statements to execute you can use a block as well.
Task.Factory.StartNew(() =>
{
// do something
// do more stuff
// done
}).ContinueWith((completedTask) =>
{
// if you were computing a value with the task
// you can now do something with it
// this is like a callback method, but defined inline
// use ui's dispatcher if you need to interact with ui compontents
UI.Label.Dispatcher.Invoke(new Action(() =>
UI.Item.Label.Text = completedTask.Result;
}
The upcoming async features that are being released in the next .net version actually streamline this even more! But since it uses tasks you will still want to get comfortable with using them.
// this will begin the operation, then return control back to the ui so it does not hang.
var result = await Object.PerformLongTask();
// once the long task is completed then it continues and you can use the result
UI.Item.Label = result;
To give a real example, here is some code from an FTP client I wrote which has has a WPF front end. When the start button is clicked the ftp transfer is launched in it's own task, then a while loop which updates the interface every half a second is launched in a task, so neither interferes with the interface thread. Again it's the same code, just wrapped in lambada's.
private void btnStart_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
ftp.Mirror(#"C:\LocalFolder", "/RemoteFolder", 10));
Task.Factory.StartNew(() =>
{
while (true)
{
lbPercentSuccess.Dispatcher.Invoke(new Action(() =>
{
lbPercentSuccess.Content = ftp.FtpProgress.SuccessPercentage;
lbPercentError.Content = ftp.FtpProgress.ErrorPercentage;
lbPercentTotal.Content = ftp.FtpProgress.TotalPercentage;
lbDuration.Content = ftp.FtpProgress.Duration;
}));
Thread.Sleep(500);
}
});
}
This is not possible to my knowledge. You can only run and invoke individual methods or queue them on separate threads when need be. Setting an actual object on a separate thread defeats your purpose. This is because you only going to harness the benefits of multithreading when invoking a method on a separate thread not an object.
then reassign the del to MethodTwo... and so on. This is made easier if you conform to a method signature.
Possible solution:
Thread threadTest = new Thread(new ThreadStart(MethodOne));
threadTest = new Thread(new ThreadStart(MethodTwo));
threadTest.Start();
Or
Action del = TestClass.MethodOne;
IAsyncResult result = del.BeginInvoke(null, null);
Func<int,int> del = TestClass.MethodOne;
IAsyncResult result = del.BeginInvoke(11,null, null);
int value = del.EndInvoke(result);
It's not simple, but have a look at this. It's a nice explination of how to use cross thread communication.
http://www.codeproject.com/KB/cs/delegatequeue.aspx
So far, this is what I found (from iPhone development). The Run loop acts like a spine that invokes various methods. It is implemented like the following:
A more elegant solution is welcomed.
class MyClass
{
public MyClass(MainForm frm)
{
_mainForm = frm;
}
private MainForm _mainForm;
public bool IsRunning = true;
public void Run()
{
_mainForm.Log(Thread.CurrentThread.ManagedThreadId.ToString() + "-Run.start");
while (IsRunning)
{
if (_runSleepMilliSeconds != null)
{
_Sleep(_runSleepMilliSeconds ?? 3000);
_runSleepMilliSeconds = null;
}
}
_mainForm.Log(Thread.CurrentThread.ManagedThreadId.ToString() + "-Run.done");
}
private int? _runSleepMilliSeconds = null;
public void Sleep(int milliseconds)
{
_runSleepMilliSeconds = milliseconds;
}
private void _Sleep(int milliseconds)
{
_mainForm.Log(Thread.CurrentThread.ManagedThreadId.ToString() + "-Run.sleep for " + milliseconds.ToString());
Thread.Sleep(milliseconds);
_mainForm.Log(Thread.CurrentThread.ManagedThreadId.ToString() + "-Run.woke up");
}
}

How to ensure run of a thread exactly after end of running of a specifc number of other threads?

I have a class in C# like this:
public MyClass
{
public void Start() { ... }
public void Method_01() { ... }
public void Method_02() { ... }
public void Method_03() { ... }
}
When I call the "Start()" method, an external class start to work and will create many parallel threads that those parallel threads call the "Method_01()" and "Method_02()" form above class. after end of working of the external class, the "Method_03()" will be run in another parallel thread.
Threads of "Method_01()" or "Method_02()" are created before creation of thread of Method_03(), but there is no guaranty to end before start of thread of "Method_03()". I mean the "Method_01()" or the "Method_02()" will lost their CPU turn and the "Method_03" will get the CPU turn and will end completely.
In the "Start()" method I know the total number of threads that are supposed to create and run "Method_01" and "Method_02()". The question is that I'm searching for a way using semaphore or mutex to ensure that the first statement of "Method_03()" will be run exactly after end of all threads which are running "Method_01()" or "Method_02()".
Three options that come to mind are:
Keep an array of Thread instances and call Join on all of them from Method_03.
Use a single CountdownEvent instance and call Wait from Method_03.
Allocate one ManualResetEvent for each Method_01 or Method_02 call and call WaitHandle.WaitAll on all of them from Method_03 (this is not very scalable).
I prefer to use a CountdownEvent because it is a lot more versatile and is still super scalable.
public class MyClass
{
private CountdownEvent m_Finished = new CountdownEvent(0);
public void Start()
{
m_Finished.AddCount(); // Increment to indicate that this thread is active.
for (int i = 0; i < NUMBER_OF_THREADS; i++)
{
m_Finished.AddCount(); // Increment to indicate another active thread.
new Thread(Method_01).Start();
}
for (int i = 0; i < NUMBER_OF_THREADS; i++)
{
m_Finished.AddCount(); // Increment to indicate another active thread.
new Thread(Method_02).Start();
}
new Thread(Method_03).Start();
m_Finished.Signal(); // Signal to indicate that this thread is done.
}
private void Method_01()
{
try
{
// Add your logic here.
}
finally
{
m_Finished.Signal(); // Signal to indicate that this thread is done.
}
}
private void Method_02()
{
try
{
// Add your logic here.
}
finally
{
m_Finished.Signal(); // Signal to indicate that this thread is done.
}
}
private void Method_03()
{
m_Finished.Wait(); // Wait for all signals.
// Add your logic here.
}
}
This appears to be a perfect job for Tasks. Below I assume that Method01 and Method02 are allowed to run concurrently with no specific order of invocation or finishing (with no guarantee, just typed in out of memory without testing):
int cTaskNumber01 = 3, cTaskNumber02 = 5;
Task tMaster = new Task(() => {
for (int tI = 0; tI < cTaskNumber01; ++tI)
new Task(Method01, TaskCreationOptions.AttachedToParent).Start();
for (int tI = 0; tI < cTaskNumber02; ++tI)
new Task(Method02, TaskCreationOptions.AttachedToParent).Start();
});
// after master and its children are finished, Method03 is invoked
tMaster.ContinueWith(Method03);
// let it go...
tMaster.Start();
What it sounds like you need to do is to create a ManualResetEvent (initialized to unset) or some other WatHandle for each of Method_01 and Method_02, and then have Method_03's thread use WaitHandle.WaitAll on the set of handles.
Alternatively, if you can reference the Thread variables used to run Method_01 and Method_02, you could have Method_03's thread use Thread.Join to wait on both. This assumes however that those threads are actually terminated when they complete execution of Method_01 and Method_02- if they are not, you need to resort to the first solution I mention.
Why not use a static variable static volatile int threadRuns, which is initialized with the number threads Method_01 and Method_02 will be run.
Then you modify each of those two methods to decrement threadRuns just before exit:
...
lock(typeof(MyClass)) {
--threadRuns;
}
...
Then in the beginning of Method_03 you wait until threadRuns is 0 and then proceed:
while(threadRuns != 0)
Thread.Sleep(10);
Did I understand the quesiton correctly?
There is actually an alternative in the Barrier class that is new in .Net 4.0. This simplifies the how you can do the signalling across multiple threads.
You could do something like the following code, but this is mostly useful when synchronizing different processing threads.
public class Synchro
{
private Barrier _barrier;
public void Start(int numThreads)
{
_barrier = new Barrier((numThreads * 2)+1);
for (int i = 0; i < numThreads; i++)
{
new Thread(Method1).Start();
new Thread(Method2).Start();
}
new Thread(Method3).Start();
}
public void Method1()
{
//Do some work
_barrier.SignalAndWait();
}
public void Method2()
{
//Do some other work.
_barrier.SignalAndWait();
}
public void Method3()
{
_barrier.SignalAndWait();
//Do some other cleanup work.
}
}
I would also like to suggest that since your problem statement was quite abstract, that often actual problems that are solved using countdownevent are now better solved using the new Parallel or PLINQ capabilities. If you were actually processing a collection or something in your code, you might have something like the following.
public class Synchro
{
public void Start(List<someClass> collection)
{
new Thread(()=>Method3(collection));
}
public void Method1(someClass)
{
//Do some work.
}
public void Method2(someClass)
{
//Do some other work.
}
public void Method3(List<someClass> collection)
{
//Do your work on each item in Parrallel threads.
Parallel.ForEach(collection, x => { Method1(x); Method2(x); });
//Do some work on the total collection like sorting or whatever.
}
}

Categories