I am writing a GUI app for monitoring and I'd like to get some advice on it's logic. Basically all the app needs to do is connect to a distant server every x minutes, check if something was changed, get changes if any, act upon them (update local db and so on, depending on changes).
My first idea was:
Have a checkbox (monitoring on/off). On click (if checked) starts a Timer.
Timer launches a BackgroundWorker in it's Tick method.
DoWork method does the connecting / retrieving info stuff
a) on WorkDone handler method gets the info from background worker and does local updates with it
b) on WorkDone handler method triggers one or more of custom events "SomethingChanged" depending on changes it got; EventListeners handle local updates from there.
My main problem is calling Worker from Timer since I added Worker to the Form and now they are on different threads (is that correct description?) and then passing results around is a similar problem. I was reading about delegates but still not sure what to use when and how, and if it's really necessary in the first place. Do I need both bgWorker and Timer? Do I need custom events or can I just do all work inside workDone with Switch(result)? Is this general principle good in the first place, maybe there's something better and I am reinventing the wheel? Thank you in advance!
From an architecture point of view:
Message Queues decouple bits of your application. You can in Windows Forms applications rely on the Message Queue that Windows creates and manages for you. Google for PostMessage/GetMessage etc. This is generally called "message passing".
Typical Arcitecture
One part of your app "pushes" a request into a queue
Some other part of your app "pulls" a request from a queue and writes a result to a second queue.
The first part can then "pull" requests from the second "results" queue and display to a user.
So it looks like this:
App --> REQUESTS QUEUE --> processing engine --> RESULTS QUEUE --> App
The processing engine could be in the same app, on the same thread or in a different thread/process (or even different machine).
You can use simple queues : say a Queue<string>() (as long as you use locks to access it) or increase complexity or more and more complex/functional queues.
Issues with the naive strategy and other solutions ... things to think about:
What happens if you make a new request while the old one has not yet completed?
What happens if an error occurs? Do you want errors inline? You can use another queue for errors?
Do you want retries?
What happens if a message is lost? (i.e. a request was pushed, but no response comes in...)? There are transactional queues etc.
Sample Code
object oLock = new object();
Queue<string> requests = new Queue<string>();
Queue<string> responses = new Queue<string>();
Thread mThread;
AutoResetEvent mEvent = new AutoResetEvent(false);
public Form1()
{
InitializeComponent();
mThread = new Thread(ProcessingEngine);
mThread.IsBackground = true;
mThread.Start();
}
private void ProcessingEngine()
{
string result;
string request = null;
while (true)
{
try
{
mEvent.WaitOne();
lock (oLock)
{
request = requests.Dequeue();
}
var wc = new WebClient();
result = wc.DownloadString(request);
lock (oLock)
{
responses.Enqueue(result);
}
}
catch (Exception ex)
{
lock (oLock)
{
responses.Enqueue(ex.ToString());
}
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
lock (oLock)
{
//Stick in a new request
requests.Enqueue("http://yahoo.com");
//Allow thread to start work
mEvent.Set();
//Check if a response has arrived
if (responses.Any())
{
var result = responses.Dequeue();
listBox1.Items.Add(result.Substring(1,200));
}
}
}
}
If you use System.Windows.Forms.Timer instead of System.Threading.Timer, your Tick handler will be called from Form's message loop and you'll have full access to all controls - it will be safe to call bgWorker.RunWorkerAsync(). As for retrieving results - RunWorkerCompleted is also called from message loop thread and you can safetly update your UI here.
The solution is simple - INVOKE back into the main thread. THere is an Invoke method on the winform control. This will basically change threads for execution to the UI thread, and allow you to manipulate the UI.
Do that "block" (i.e. not once per control but once when you have news).
Related
I have several forms applications, that rely on worker threads to do all the processing. They talk to an external application that in some cases relies on simulating user interface (copy/paste functionality).
In each case I have a RichTextBox in the form, to provide feedback to the user during progressing - which needs to be async so that the textbox can update in real time. (disclaimer: this was my first dive into the world of threading and async processes, the feedback part works at least!)
I have a class "AppTrack" that is being used to monitor all these applications for usage, reporting, and better exception handling. In it are 2 functions (shown below) I use to fire the worker threads "safely", along with turning on/off certain form controls to prevent further user interaction.
public static void DoInSafeThread(Action ActualThreadFunction, List<Control> FormControls = null)
{
System.Action<System.Exception> exception = null;
Thread thread = new Thread(
() => AppTrack.SafeExecute(() => ActualThreadFunction(), exception, FormControls)
);
thread.IsBackground = true;
thread.Start();
}
private static void SafeExecute(Action ActualThreadFunction, Action<Exception> handler, List<Control> FormControls)
{
try
{
DisableControls(FormControls);
ActualThreadFunction.Invoke();
EnableControls(FormControls);
}
catch (Exception ex)
{
Handler(ex);
}
}
This is causing me a big problem if there is a list of things to process, like the snippet below. It will fire a new worker thread for each one, and the nature of the interface with the external application means the processes interfere and give bad results/errors.
foreach (IOccurrences s in sel)
{
AppTrack.DoInSafeThread(delegate()
{
CableChecking.CheckCables((IOccurrences)s, rtbLog, CableData, materials);
}, FormControls);
}
Thoughts on solution
Have a single thread used in my "AppTrack" class. Assign it a new operation as it completes the previous one, or queue them up to run in order and eventually feedback to the GUI thread that all jobs are complete. But, trying to implement that I hit a brick wall... Is this even the correct approach?
I was hoping to find things like thread.BindNewAction but, that's apparently not right...
I'm a newbie in C#, and I'm going to develop a small program using a third party network library to send the requests.
Suppose there have some requests (just simple strings) stored in the queue qTasks, and it will handle those requests one by one with the order as submitted, the queue can be updated during execution, and it should be stopped whenever there has error returned.
I can just use a for loop to call the send request command in the array one by one, but unfortunately the sendrequest command is an async method with callback OnStageChanged, and I need to check the result before sending the next request when the status is "Done".
I'm now using the following method to handle it:
In the main UI Thread,
// Put those request text in a queue names qTasks, then call a goNextTask() to process the request one by one.
// The queue can be updated by the UI thread at anytime, goNextTask will be called periodically to handle those pending request in the queue.
private void goNextTask(bool lastSuccess = true)
{
if (lastSuccess)
{
if (qTasks.Count > 0)
{
// continue to next request
string requestText = qTasks.Dequeue();
SendRequest(requestText, OnStageChangeHandler);
} else {
// Report for all request sent successfully
}
} else {
// stop and show error
}
}
The callback method OnStageChangeHandler will be called by the library whenever the stage changes, and it will have state "Done" when completed.
private void OnStageChangeHandler(object sender, StageChangeEventArgs e)
{
if (e.newState == SessionStates.Done)
{
// check result here
bool success = <...>
// then call the goNextTask in UI thread with the result of current request.
Application.Current.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
(Action)(() => goNextTask(success)));
}
}
Although it works fine now, I think it's a little bit stupid as it has a somewhat recursive flow (A -> B -> A -> B ->....).
I learnt that MS has improved the web request handling, so that it can work in sync mode.
I'd like to know if I can have a wrapper to make the above async call work as a sync call, so that it can be done in a simple flow as a loop like that:
while (qTaks.Count > 0)
{
if (!sendAndWaitReturn(qTasks.Dequeue())) {
// Report error and quit
}
}
// all tasks completed
This sendAndWaitReturn method will send the request, then wait for the status "Done", and then return the result.
I found some example that may use a control flag to indicate the status of the current request, and the callback function will update this control flag, while the UI thread will loop on this flag using a while loop:
while (!requestDone);
so that it will not continue to nextRequest until requestDone. But in this case, the UI will be blocked.
Is there any better way to convert the async call to work as a sync call without blocking the UI thread?
The difficulty you're going to run into is you have conflicting desires. On one hand, you want to avoid blocking the UI thread. On the other hand, you don't want to run things asynchronously and so you're going to block the UI thread.
You're going to have to pick one, and there's absolutely no reason to keep on doing things synchronously (especially in light of blocking the UI thread). If it hurts when you do that, don't do that.
You haven't specified, but I'm guessing that you're starting this processing from a button click event. Make the method invoked by that click event async. For example:
private async void StartProcessing_Click(object sender, EventArgs e)
{
await Task.Run(() => StartProcessing());
}
There, you've started processing and the UI thread isn't tied up.
The next thing is that, you're right, having the event behave in that cyclical manner is silly. The event is to notify someone that the state has changed, its goal isn't to manage queue policy. The queue should manage queue policy (or if you'd rather not abstract that out, the method that processes requests).
So how would you do that? Well, you've said that SendRequest hands the session object back to the caller. The caller is presumably the one who is orchestrating queue policy and determining whether or not to call SendRequest again.
Have the caller check the session object for validity and decide whether to keep going based on that.
Additionally, I'm unfamiliar with that particular library, but briefly glancing at the documentation it looks like there's also a SendRequestAndWait() method with the same signature and that sounds like it might better meet your needs.
I have a windows service that is designed to handle incoming data, process it, and alert users if necessary. One thing that I am having trouble figuring out is how to keep a thread alive.
I have a few classes that share a ConcurrentBag of Device objects. The DeviceManager class is tasked with populating this collection and updating the device objects if a parameter about a device changes in the database. So for example, in the database someone updates device 23 to have a normal high of 50F. The DeviceManager would update the appropriate device in memory to have this new value.
Oracle provides an event handler to be notified when a table changes (docs here). I want to attach an event handler so I can be notified when to update my devices in memory. The problem is, how can I create a thread for my DeviceManager to work in and for it to just idle in the thread until the event occurs and is handled there? I would like to have the event fire and be handled in this thread instead of the main one.
You can create a separate worker thread when your service starts up. The worker thread will connect to the database and listen for change notifications, and update your ConcurrentBag accordingly. When the service is shut down, you can gracefully terminate the thread.
MSDN has an example that I think will help you: How to: Create and Terminate Threads
There are a large number of synchronization techniques available in .NET, and to discuss the entire scope would be too broad to address here. However, you should look at the Monitor class, with its Wait() and Pulse() methods.
For example:
private readonly object _lockObj = new object();
public void StartThread()
{
new Thread(ThreadProc).Start();
}
public void SignalThread()
{
lock (_lockObj)
{
// Initialize some data that the thread will use here...
// Then signal the thread
Monitor.Pulse(_lockObj);
}
}
private void ThreadProc()
{
lock (_lockObj)
{
// Wait for the signal
Monitor.Wait(_lockObj);
// Here, use data initialized by the other thread
}
}
Of course you can put the thread's locking/waiting code in a loop if you need for the thread to repeat the operation.
It looks like there's no shortage of other questions involving the Monitor class on SO:
https://stackoverflow.com/search?q=%5Bc%23%5D+monitor+pulse+wait
And of course, the documentation on MSDN has other examples as well.
I am developing c# windows service that will be watching several files, folders and DB tables for any changes. There are three types of watchers (I call them watchers).
FileWatcher : Constantly watcher for a file using .Net FileSystemWatcher and raises an event where alert is to be sent. After alert is sent, watch functionality resumes.
FolderWatcher : Constantly watcher for a folder using .Net Timer and raises an event where alert is to be sent upon certain conditions. After alert is sent, watch functionality resumes.
DBWatcher: Executes an SQL query after each minute (Timer) and sends an alert if the result is wrong.
You can guess that these all watchers will run all the time where windows service is running.
They all implement an interface IWatcher and provide a method BeginWatch that performs the operations needed for each watcher, such as querying the DB every minute using timer (if watcher is DBWatcher). The input for creating these watchers is an XML file. It contains something like following:
<?xml version="1.0" encoding="utf-8"?>
<watchlist>
<watcher type="FolderWatcher">
<path>D:\Projects\.Net\V1\</path>
<PauseInMinBtwAlerts>1</PauseInMinBtwAlerts>
<alert>xxx#xxx.com</alert>
</watcher>
<watcher type="FileWatcher">
<path>D:\Projects\.Net\</path>
<fileName>e.txt</fileName>
<alert>yyy#yyy.com</alert>
</watcher>
<watcher type="DBWatcher">
<sqlquery>select blah blah blah ... </sqlquery>
<connectionstring>connection string for the DB</connectionstring>
<alert>yyy#yyy.com</alert>
</watcher>
</watchlist>
This XML tells us how many watchers are to be created. There can be a dozens of watchers created.
Due to some issues we faced, we have decided that each watcher will be run on a different Thread. So in case of an unhandled exeption, only that thread can be stopped/killed and we inform the IT department through an email alert about the situation. We must be able to resume it later.
Now i m confused. as there are Threads, Async tasks, pooled threads, background threads etc etc. what should I use???/ I m new to this threading.
Let me tell you my requirement and then you may guide me to some proper solutions:
I want each watcher to run in a separate thread.
Thread MUST run continuously and my watcher must be able to watch until the windows service itself shuts down.
Thread must be able to communicate with its parent thread (the class where each thread is created) to update it about its status.
Any unhandled exception in a thread must be caught in the thread itself and then communicated to the parent class (using 3rd point).
I have created the following class that will be responsible for creating, communicating with, and managing all threads:
public class WatcherThreadsManager
{
//This will keep list of all active threads ... as I will be communicating with them later
private List<Thread> _watcherThreads;
public WatcherThreadsManager()
{
this._watcherThreads = new List<Thread>();
}
//I will call this method and pass in any watcher which i want to run in a new thread
public void CreateWatcherThread(IWatcher watcher)
{
Thread _watcher = new Thread(_createWatcherThread);
//the Copy() will produce its deeply copied copy ... i wanted to make sure thread works on a free object .. not sure
_watcher.Start(watcher.Copy());
//Add Thread to threads' list
this._watcherThreads.Add(_watcher);
}
private void _createWatcherThread(object wat)
{
IWatcher watcher = wat as IWatcher;
try
{
//the following function will begin the watch.
//I dont want any loop either .. as i want to call the BeginWatch() method only once.
watcher.BeginWatch();
}
catch (Exception ex)
{
// i should be able to inform the parent thread about the exception so this thread is set to sleep. as we can reactivate it later when the issue fixes.
// how to do that?
}
}
}
What would be the best way to achieve what I want?
You can achieve all of your requirements by using Tasks, here are few links for further reading:
Creating threads - Task.Factory.StartNew vs new Thread()
Best Practice LongRunning Task creation
Task Report Progress
Handling Task exceptions
Good luck!
Due to some issues we faced, we have decided that each watcher will be run on a different Thread. So in case of an unhandled exeption, only that thread can be stopped/killed
This sounds like you don't need threads, you need to catch your exceptions. Why don't you do that?
Lets say I have a component called Tasking (that I cannot modify) which exposes a method “DoTask” that does some possibly lengthy calculations and returns the result in via an event TaskCompleted. Normally this is called in a windows form that the user closes after she gets the results.
In my particular scenario I need to associate some data (a database record) with the data returned in TaskCompleted and use that to update the database record.
I’ve investigated the use of AutoResetEvent to notify when the event is handled. The problem with that is AutoResetEvent.WaitOne() will block and the event handler will never get called. Normally AutoResetEvents is called be a separate thread, so I guess that means that the event handler is on the same thread as the method that calls.
Essentially I want to turn an asynchronous call, where the results are returned via an event, into a synchronous call (ie call DoSyncTask from another class) by blocking until the event is handled and the results placed in a location accessible to both the event handler and the method that called the method that started the async call.
public class SyncTask
{
TaskCompletedEventArgs data;
AutoResetEvent taskDone;
public SyncTask()
{
taskDone = new AutoResetEvent(false);
}
public string DoSyncTask(int latitude, int longitude)
{
Task t = new Task();
t.Completed = new TaskCompletedEventHandler(TaskCompleted);
t.DoTask(latitude, longitude);
taskDone.WaitOne(); // but something more like Application.DoEvents(); in WinForms.
taskDone.Reset();
return data.Street;
}
private void TaskCompleted(object sender, TaskCompletedEventArgs e)
{
data = e;
taskDone.Set(); //or some other mechanism to signal to DoSyncTask that the work is complete.
}
}
In a Windows App the following works correctly.
public class SyncTask
{
TaskCompletedEventArgs data;
public SyncTask()
{
taskDone = new AutoResetEvent(false);
}
public string DoSyncTask(int latitude, int longitude)
{
Task t = new Task();
t.Completed = new TaskCompletedEventHandler(TaskCompleted);
t.DoTask(latitude, longitude);
while (data == null) Application.DoEvents();
return data.Street;
}
private void TaskCompleted(object sender, TaskCompletedEventArgs e)
{
data = e;
}
}
I just need to replicate that behaviour in a window service, where Application.Run isn’t called and the ApplicationContext object isn’t available.
I've had some trouble lately with making asynchronous calls and events at threads and returning them to the main thread.
I used SynchronizationContext to keep track of things. The (pseudo)code below shows what is working for me at the moment.
SynchronizationContext context;
void start()
{
//First store the current context
//to call back to it later
context = SynchronizationContext.Current;
//Start a thread and make it call
//the async method, for example:
Proxy.BeginCodeLookup(aVariable,
new AsyncCallback(LookupResult),
AsyncState);
//Now continue with what you were doing
//and let the lookup finish
}
void LookupResult(IAsyncResult result)
{
//when the async function is finished
//this method is called. It's on
//the same thread as the the caller,
//BeginCodeLookup in this case.
result.AsyncWaitHandle.WaitOne();
var LookupResult= Proxy.EndCodeLookup(result);
//The SynchronizationContext.Send method
//performs a callback to the thread of the
//context, in this case the main thread
context.Send(new SendOrPostCallback(OnLookupCompleted),
result.AsyncState);
}
void OnLookupCompleted(object state)
{
//now this code will be executed on the
//main thread.
}
I hope this helps, as it fixed the problem for me.
Maybe you could get DoSyncTask to start a timer object that checks for the value of your data variable at some appropriate interval. Once data has a value, you could then have another event fire to tell you that data now has a value (and shut the timer off of course).
Pretty ugly hack, but it could work... in theory.
Sorry, that's the best I can come up with half asleep. Time for bed...
I worked out a solution to the async to sync problem, at least using all .NET classes.
Link
It still doesn't work with COM. I suspect because of STA threading. The Event raised by the .NET component that hosts the COM OCX is never handled by my worker thread, so I get a deadlock on WaitOne().
someone else may appreciate the solution though :)
If Task is a WinForms component, it might be very aware of threading issues and Invoke the event handler on the main thread -- which seems to be what you're seeing.
So, it might be that it relies on a message pump happening or something. Application.Run has overloads that are for non-GUI apps. You might consider getting a thread to startup and pump to see if that fixes the issue.
I'd also recommend using Reflector to get a look at the source code of the component to figure out what it's doing.
You've almost got it. You need the DoTask method to run on a different thread so the WaitOne call won't prevent work from being done. Something like this:
Action<int, int> doTaskAction = t.DoTask;
doTaskAction.BeginInvoke(latitude, longitude, cb => doTaskAction.EndInvoke(cb), null);
taskDone.WaitOne();
My comment on Scott W's answer seems a little cryptic after I re-read it. So let me be more explicit:
while( !done )
{
taskDone.WaitOne( 200 );
Application.DoEvents();
}
The WaitOne( 200 ) will cause it to return control to your UI thread 5 times per second (you can adjust this as you wish). The DoEvents() call will flush the windows event queue (the one that handles all windows event handling like painting, etc.). Add two members to your class (one bool flag "done" in this example, and one return data "street" in your example).
That is the simplest way to get what you want done. (I have very similar code in an app of my own, so I know it works)
Your code is almost right... I just changed
t.DoTask(latitude, longitude);
for
new Thread(() => t.DoTask(latitude, longitude)).Start();
TaskCompleted will be executed in the same thread as DoTask does. This should work.