I don't like this code but I always get confused with threads so wanted someone else's input before I suggest a change; Is this thread safe (Psuedo code though based on C#):
class ThreadCreator
{
private AnObject obj = new AnObject();
public ThreadCreator()
{
for (int i = 0; i < 100; ++i)
{
ThingToThread th = new ThingToThread();//don't care about losing ref to th for this question
th.sendMsg = this.getMessage;
Thread t = new Thread(th.doThing);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
}
public void getMessage( string stuff )
{
...
obj.DoThing(stuff);
...
}
}
class ThingToThread
{
public delegate void sendMsg(string stuff);
public void doThing()
{
...
this.sendMsg("ohh that's interesting");
...
}
}
You aren't calling back to the any other thread.
Your code will execute the delegate on the new thread, just like any other function call.
If getMessage is not thread-safe, your code will break.
Your example isn't thread safe, if you wanted thread-safety I would very much advise using a BackgroundWorker for executing in a new thread, but posting messages back to the main thread.
For example:
class ThreadCreator
{
private AnObject obj = new AnObject();
public ThreadCreator()
{
for (int i = 0; i < 100; ++i)
{
ThingToThread th = new ThingToThread();
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += th.DoWork;
worker.ProgressChanged += WorkerProgressChanged;
worker.RunWorkerAsync();
}
}
private void WorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
string stuff = e.UserState as string;
obj.DoThing(stuff);
}
}
And your ThingToThread DoWork method would look like:
public void DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
worker.ReportProgress(50, "Half way there");
worker.ReportProgress(100, "Finished");
}
Related
thanks for reading this topic.
For a new WPF application (build in C#) I have a question regarding the design.
The past few days I have read a lot about Async programming in C# (based on .NET 4.5).
What we would like to do is: Create a new async thread, which does independent background tasks. When this thread has data available: then send this data to the main program (by an public interface). So, the thread will set data in the main program and immediately return to the thread again. The main program will raise an event (INotifyPropertyChanged) when data has been changed.
What will be the best way to create this Async thread? Or at least, what would be the best way to design this feature?
At the moment I have build an application which creates a thread.
This does not work Async at the moment:
public MainWindow()
{
InitializeComponent();
InitGuiInterface(this);
//Create thread
new OuterLabel_Thread(this);
}
And the class "OuterLabel_Thread.cs"here below:
public class OuterLabel_Thread
{
private MainWindow context = null;
private bool exit = false;
private int count = 0;
public OuterLabel_Thread(MainWindow context)
{
this.context = context;
Console.WriteLine("Running sample thread");
Thread thread = new Thread(delegate ()
{
Console.WriteLine("Sample thread started");
//start new task
//run();
Task.Factory.StartNew(run);
});
thread.Start();
}
public void Exit()
{
exit = true;
}
private void run()
{
while (!exit)
{
DateTime Time1 = DateTime.Now;
if (context != null && context.GuiInterface != null)
{
//context.GuiInterface.UpdateThreadCount(count, "label_code_content");
}
Console.WriteLine("Background thread count = " + count);
count++;
if (count > 1000)
{
exit = true;
}
//Console.WriteLine((DateTime.Now - Time1).TotalMilliseconds.ToString());
Thread.Sleep(10);
}
}
}
Many thanks in advance!
Kind regards,
Rein.
as you want to keep the thread alive and as far as I understand, you don't know exactly when or if you will reach the 1000 mark, async might be the wrong choice. Correct me if i'm wrong.
For your case I would recommend using the BackgroundWorker:
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
int count = 0;
BackgroundWorker worker = sender as BackgroundWorker;
while (!exit)
{
DateTime Time1 = DateTime.Now;
worker.ReportProgress(count);
count++;
if (count > 1000)
{
exit = true;
}
Thread.Sleep(10);
}
}
// This event handler updates the progress.
private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
resultLabel.Text = ("Background thread count = " + e.ProgressPercentage.ToString());
}
private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true)
{
resultLabel.Text = "Canceled!";
}
else if (e.Error != null)
{
resultLabel.Text = "Error: " + e.Error.Message;
}
else
{
resultLabel.Text = "Done!";
}
}
The best way would be using async+await and tasks.
private async void LaunchButton_OnClick(object sender, RoutedEventArgs e)
{
resultLabel.Content = "Task running";
resultLabel.Content = await SomeLongRunningTaskAsync();
}
private Task<string> SomeLongRunningTaskAsync()
{
return Task.Run(
() =>
{
// Put your background work in here. with Task.Run it's not going to run on UI
int count = 0;
while (count < 1000)
{
count++;
Thread.Sleep(10);
}
return "Task done";
});
}
I can't figure out if you are looking for a service or a long running task.
Since the others have good examples of long running tasks I've made a Service
It uses some advanced concpets like SynchronizationContext that you should read up on before using this in production code. Google async await and Stephen Cleary.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var foo = new FooService();
foo.StartService(); // UI thrad calling
}
}
public class FooService
{
private SynchronizationContext _context;
private CancellationTokenSource _cts;
private CancellationToken _token;
private Task _task;
public void StartService()
{
_context = SynchronizationContext.Current; // Depends on the UI thread being the one to start the service or this will fail
_cts = new CancellationTokenSource(10000); // Run for 10 seconds
_token = _cts.Token;
_task = Task.Run(() => Run(), _token);
}
public async Task Stop()
{
_cts.Cancel();
await _task; // wait for task to finish
}
private void Run()
{
while (!_token.IsCancellationRequested)
{
// Do work
Thread.Sleep(1000);
// Alternative use Control.Invoke() if you have access to a UI element, to delegate to the UI thread
_context.Send((id) => Console.WriteLine($"Delegate from thread {id} to thread {Thread.CurrentThread.ManagedThreadId}"), Thread.CurrentThread.ManagedThreadId);
}
}
}
Every time when timer invoke UpdateDocumentsListFromServer UI freezes for 3 seconds. How to update list in async style under .net 3.5?
ViewModel:
public class ShippingDocumentsRegisterViewModel : ViewModelBase
{
ShippingDocumentsModel model = new ShippingDocumentsModel();
DispatcherTimer timer = new DispatcherTimer();
BackgroundWorker BW = new BackgroundWorker();
public ShippingDocumentsRegisterViewModel()
{
timer = new DispatcherTimer();
timer.Tick += new EventHandler(UpdateDocumentsListFromServer);
timer.Interval = new TimeSpan(0, 0, 10);
timer.Start();
this.Columns = model.InitializeColumns();
BW.DoWork += UpdateDocumentsList;
BW.RunWorkerAsync();
}
public void UpdateDocumentsList(object o, EventArgs args)
{
this.ShippingDocuments = model.GetDocuments();
}
public void UpdateDocumentsListFromServer(object o, EventArgs args)
{
// Taking a lot of time. How to do it async?
var tempDocuments = model.GetDocumentsFromServer();
foreach (var item in tempDocuments)
{
this.shippingDocuments.Add(item);
}
//
}
private ObservableCollection<ShippingDocument> shippingDocuments;
public ObservableCollection<ShippingDocument> ShippingDocuments
{
get
{
return shippingDocuments;
}
private set
{
shippingDocuments = value;
RaisePropertyChanged("ShippingDocuments");
}
}
public ObservableCollection<ShippingDocumentColumDescriptor> Columns { get; private set; }
}
GetDocumentsFromServer look like
public ObservableCollection<ShippingDocument> GetDocumentsFromServer()
{
System.Threading.Thread.Sleep(3000);
return new ObservableCollection<ShippingDocument> { new ShippingDocument { Name = "Test" } };
}
You could also use a background worker that reports progress to the UI
public ShippingDocumentsRegisterViewModel()
{
BW.DoWork += UpdateDocumentsListFromServer;
BW.RunWorkerCompleted += BW_RunWorkerCompleted;
BW.WorkerReportsProgress = true;
BW.ProgressChanged += UpdateGui;
BW.RunWorkerAsync();
}
public void UpdateGui(object o, EventArgs args)
{
foreach (var item in tempDocuments)
{
this.shippingDocuments.Add(item);
}
}
public void UpdateDocumentsListFromServer(object o, EventArgs args)
{
while (true) {
System.Threading.Thread.Sleep(3000);
tempDocuments = GetDocumentsFromServer();
BW.ReportProgress(0);
}
}
int num = 0;
public ShippingDocument[] GetDocumentsFromServer()
{
System.Threading.Thread.Sleep(3000);
return new ShippingDocument[1] { new ShippingDocument { Name = "Test" + num++} };
}
private ShippingDocument[] tempDocuments = new ShippingDocument[0];
Just offload it to a new thread using Task and Async/Await like so:
public async void UpdateDocumentsListFromServer(object o, EventArgs args)
{
// This will execute async and return when complete
await Task.Run(()=>{
var tempDocuments = model.GetDocumentsFromServer();
foreach (var item in tempDocuments)
{
this.shippingDocuments.Add(item);
}
});
//
}
Keep in mind this updates on a different thread then the UI. So it is not allowed to touch anything on the UI thread or you will get threading issues. So if shippingDocuments was created on the UI thread and is not thread-safe you could instead return a collection of items then add them:
public async void UpdateDocumentsListFromServer(object o, EventArgs args)
{
// Execute on background thread and put results into items
var items = await Task.Run(()=>{
var tempDocuments = model.GetDocumentsFromServer();
return tempDocuments;
});
//add occurs on UI thread.
this.shippingDocuments.AddRange(tempDocuments);
}
Use a regular Timer and only dispatch the access to shippingDocuments.
As mentioned in comment, you can make use of Timers instead of DispatcherTimer. DispactherTimer will access the UIThread where as Timer use different thread from threadpool.
Also, you can dispatch an action to UIThread from different thread
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
//Do some UI stuffs
}));
Hope that helps.
I made a thread at load event like below:
Thread checkAlert = null;
bool isStop = false;
private void frmMain_Load(object sender, EventArgs e)
{
checkAlert = new Thread(CheckAlert);
checkAlert.Start();
}
void CheckAlert()
{
while (!isStop)
{
Thread.Sleep(60000);
//do work here
}
}
Is there any way to resume the checkAlert thread during it's sleep period?( Thread.Sleep(60000);)
I tried using Thread.Interrupt() but it flows a ThreadInterruptedException, how should I handle this exception? or is there any way to resume the thread?
Edited:
I need to wake up the thread before the "sleep" end because when the user wants to quit the program, the program will have to wait for some time before it really quits ( checkAlert is still running) Is there any way to improve this case?
Based on your comments what it looks like is you need to re-design how CheckAlert works so it does not use Sleep's at all. What you should be doing is using a Timer instead.
System.Timers.Timer timer = null;
public FrmMain()
{
InitializeComponent();
timer = new System.Timers.Timer(60000);
timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
//If you want OnTimedEvent to happen on the UI thread instead of a ThreadPool thread, uncomment the following line.
//timer.SynchronizingObject = this;
if(this.components == null)
this.components = new System.ComponentModel.Container();
//This makes it so when the form is disposed the timer will be disposed with it.
this.componets.Add(timer);
}
private void frmMain_Load(object sender, EventArgs e)
{
timer.Start();
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
//It is good practice not to do complicated logic in a event handler
// if we move the logic to its own method it is much easier to test (you are writing unit tests, right? ;) )
CheckAlert();
}
void CheckAlert()
{
//do work here
}
private void frmMain_Close(object sender, EventArgs e)
{
timer.Stop();
}
If you want the thread to exit automatically when your program quits, simply make it a background thread.
checkAlert = new Thread(CheckAlert);
checkAlert.IsBackground = true;
checkAlert.Start();
It looks to me like you're trying to create a thread which handles two types of events: do something and stop running.
Rather than using a shared variable (isStop) and some other technique to interrupt the thread in order to do work, you might want to use threading events (not to be confused high-level UI Event objects) to control your thread.
AutoResetEvent stop = new AutoResetEvent(false);
AutoResetEvent check = new AutoResetEvent(false);
private void CheckAlert() {
WaitHandle[] handles = new WaitHandle[] { stop, check };
for (;;) {
switch (AutoResetEvent.WaitAny(handles)) {
case 0:
return;
case 1:
// do work
break;
}
}
}
Calling check.Set() in your code will trigger the "do work" branch in the thread and stop.Set() will cause the thread to terminate gracefully.
Once your code has called stop.Set() to terminate the thread, it can call the thread's Join() method to wait until the thread terminates.
EDIT
I misunderstood the question. I will leave the code above in case anyone finds it useful.
If all you want to do is have a thread that performs a task once a minute and stop on demand, you can use the following code:
AutoResetEvent stop = new AutoResetEvent(false);
void CheckAlert() {
var time = new TimeSpan(0, 1, 0); // one minute
while (!stop.WaitOne(time)) {
// do work
}
}
private Thread checkThread;
private void frmMain_Load(object sender, EventArgs e) {
checkThread = new Thread(CheckAlert);
checkThread.Start();
}
private void frmMain_Close(object sender, EventArgs e) {
stop.Set(); // signal thread to stop
checkThread.Join(); // wait for thread to terminate
}
You can see an explanation on how to wake a sleeping thread here:
https://msdn.microsoft.com/en-us/library/tttdef8x%28v=vs.100%29.aspx
and this is a complete example (as you can see, Thread.Interrupt is the good choise... however you have to catch it to continue normal thread execution):
public class HVCSensor : HVCDevice, IDisposable
{
private Thread myThread;
private const int execute_timeout = ((10 + 10 + 6 + 3 + 15 + 15 + 1 + 1 + 15 + 10) * 1000);
private bool disposed = false;
private bool paused = false;
public delegate void HVCResultsHandler(HVC_RESULT res);
public event HVCResultsHandler HVCResultsArrived;
private void OnHVCResultsArrived(HVC_RESULT res)
{
if (HVCResultsArrived != null) {
HVCResultsArrived(res);
}
}
public HVCSensor() {
myThread = new Thread(new ThreadStart(this.execute));
}
private void execute(){
while (!disposed) {
if (!paused && this.IsConnected)
{
HVC_RESULT outRes;
byte status;
try
{
this.ExecuteEx(execute_timeout, activeDetections, imageAcquire, out outRes, out status);
OnHVCResultsArrived(outRes);
}
catch (Exception ex) {
}
}
else {
try
{
Thread.Sleep(1000);
}
catch (ThreadInterruptedException e)
{
}
}
}
}
public HVC_EXECUTION_IMAGE imageAcquire
{
get;
set;
}
public HVC_EXECUTION_FLAG activeDetections
{
get;
set;
}
public void startDetection() {
if(myThread.ThreadState==ThreadState.Unstarted)
myThread.Start();
}
public void pauseDetection() {
paused = true;
}
public void resumeDetection() {
paused = false;
if (myThread.ThreadState == ThreadState.WaitSleepJoin)
myThread.Interrupt();
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
disposed = true;
myThread.Interrupt();
}
}
I have a function that is called in rapid succession that has a open database connection.
my issue is that before one database connection is closed, another instance of the function is called and i could possibly receive a deadlock in the database.
I have tried:
private static WaitHandle[] waitHandles = new WaitHandle[]
{
new AutoResetEvent(false)
};
protected override void Broadcast(Data data, string updatedBy)
{
Action newAction = new Action(() =>
{
DataManagerFactory.PerformWithDataManager(
dataManager =>
{
// Update status and broadcast the changes
data.UpdateModifiedColumns(dataManager, updatedBy);
BroadcastManager.Instance().PerformBroadcast(
data,
BroadcastAction.Update,
Feature.None);
},
e => m_log.Error(ServerLog.ConfigIdlingRequestHandler_UpdateFailed() + e.Message));
}
);
Thread workerThread = new Thread(new ThreadStart(newAction));
ThreadPool.QueueUserWorkItem(workerThread.Start, waitHandles[0]);
WaitHandle.WaitAll(waitHandles);
}
but i recieve a thread error and the program freezes. It has something to do with the thread start function having no parameters i believe.
Thanks for any help
This is how it's done. Create class that does the job:
public class MyAsyncClass
{
public delegate void NotifyComplete(string message);
public event NotifyComplete NotifyCompleteEvent;
//Starts async thread...
public void Start()
{
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(DoSomeJob));
t.Start();
}
void DoSomeJob()
{
//just wait 5 sec for nothing special...
System.Threading.Thread.Sleep(5000);
if (NotifyCompleteEvent != null)
{
NotifyCompleteEvent("My job is completed!");
}
}
}
Now this is code from another class, that calls first one:
MyAsyncClass myClass = null;
private void button2_Click(object sender, EventArgs e)
{
myClass = new MyAsyncClass();
myClass.NotifyCompleteEvent += new MyAsyncClass.NotifyComplete(myClass_NotifyCompleteEvent);
//here I start the job inside working class...
myClass.Start();
}
//here my class is notified from working class when job is completed...
delegate void myClassDelegate(string message);
void myClass_NotifyCompleteEvent(string message)
{
if (this.InvokeRequired)
{
Delegate d = new myClassDelegate(myClass_NotifyCompleteEvent);
this.Invoke(d, new object[] { message });
}
else
{
MessageBox.Show(message);
}
}
Let me know if I need to explain some details.
Alternative to this is BackgroudWorker:
I have an app that has several methods that take a long time to complete. I am using a backgroundworker to run these methods and keep my UI responsive. My methods look something like
public void DoSomething()
{
while( HaveMoreWork )
{
// do work
}
}
Now i want the UI to be able to cancel this at any time so I have changed my methods to take a Backgroundworker like so
public void DoSomething(Backgroundworker worker)
{
while( HaveMoreWork && !worker.CancelationPending )
{
// do work
}
}
My question is, is there a better way to do this. Seems like passing a Backgroundwoker as an argument to all these methods is a bit messy. What is best practice for this?
I am using global variable
private BackgroundWorker _bwSearch = new BackgroundWorker();
private void InitializeBackgroundWorker()
{
_bwSearch = new BackgroundWorker();
_bwSearch.WorkerSupportsCancellation = true;
_bwSearch.DoWork += bwSearch_DoWork;
_bwSearch.RunWorkerCompleted += bwSearch_RunWorkerCompleted;
}
when clicked on stop button
private void btnCancel_Click(object sender, EventArgs e)
{
_bwSearch.Abort();
}
Updated:
Also I am using this simple helper class that is inherited from BackgroundWorker
public class AbortableBackgroundWorker : BackgroundWorker
{
private Thread _workerThread;
protected override void OnDoWork(DoWorkEventArgs e)
{
_workerThread = Thread.CurrentThread;
try
{
base.OnDoWork(e);
}
catch (ThreadAbortException)
{
e.Cancel = true;
Thread.ResetAbort();
}
}
public void Abort()
{
if (_workerThread != null)
{
_workerThread.Abort();
_workerThread = null;
}
}
}
public class DoSomethingService
{
private volatile bool _stopped = false;
public void Start(object socketQueueObject)
{
while (!_stopped)
{
...
}
}
public void Stop()
{
_stopped = true;
}
}
...
var doSomethingService = DoSomethingService();
doSomethingService.Start();
...
doSomethingService.Stop();