c# asynchronously call method - c#

There is this class unit that has a property bool status that marks whether a method, request, should be called on the unit. I have my other class, and in it, there is a method that should call request. To avoid blocking the main thread, I want to call the method asynchronously. The problem is that there isn't an event for the status change, and I don't want to make my asynchronous call do ugly stuff like:
while(!status){}unit.request(args);
or
while(!status){Thread.Sleep(100)}unit.request(args);
especially when I do not know the timescale in which status turns true.
How do I do this?
update: i forgot to mention that i cannot change unit. sorry for that.

You want to call a function (be it asynchronously or not) when a property changes. You have two choices:
Attach to an even that is signalled when the property changes
Periodically check the value of the property
You can't do the first, so you must do the second.

This is a sample of how you can manage this using an event.
Suppose this is your class
public class Unit
{
private readonly object _syncRoot = new object();
private bool _status;
public event EventHandler OnChanged;
public bool Status
{
get
{
lock (_syncRoot)
{
return _status;
}
}
set
{
lock (_syncRoot)
{
_status = value;
if (_status && OnChanged != null)
{
OnChanged.Invoke(this, null);
}
}
}
}
public void Process()
{
Thread.Sleep(1000);
Status = true;
}
}
Here is how you can use it
class Program
{
static void Main(string[] args)
{
var unit = new Unit();
unit.OnChanged += Unit_OnChanged;
Console.WriteLine("Before");
Task.Factory.StartNew(unit.Process);
Console.WriteLine("After");
Console.WriteLine("Manual blocking, or else app dies");
Console.ReadLine();
}
static void Unit_OnChanged(object sender, EventArgs e)
{
//Do your processing here
Console.WriteLine("Unit_OnChanged before");
Task.Factory.StartNew(()=>
{
Thread.Sleep(1000);
Console.WriteLine("Unit_OnChanged finished");
});
Console.WriteLine("Unit_OnChanged after");
}
}
This outputs
Before
After
Manual blocking, or else app dies
Unit_OnChanged before
Unit_OnChanged after
Unit_OnChanged finished

This is the classic polling problem, and there really isn't an elegant solution when polling is concerned. But we can work some functional programming in to get something which isn't a nightmare to use.
public static CancellationTokenSource Poll(
Func<bool> termination,
Action<CancellationToken> onexit,
int waitTime = 0,
int pollInterval = 1000)
{
var cts = new CancellationTokenSource();
var token = cts.Token;
Action dispose = cts.Cancel;
var timer = new Timer(_ =>
{
if (termination() || token.IsCancellationRequested)
{
onexit(token);
dispose();
}
}, null, waitTime, pollInterval);
dispose = timer.Dispose;
return cts;
}
Example:
var condition = false;
Poll(() => condition == true, ct => Console.WriteLine("Done!"));
Console.ReadLine();
condition = true;
Console.ReadLine();

Use a System.Threading.AutoResetEvent instead of a bool if possible:
AutoResetEvent status = new AutoResetEvent();
In your asynchronous method, wait for it:
status.WaitOne();
unit.request(args);
Then, to signal it in your other class, call Set:
status.Set();

Related

Implementing Your ThreadPool

A ThreadPool is created that does all the work on one thread and notifies when the work is done. The thread is started and the methods Execute1 and Execute2 are not displayed, but Done1 and Done2 are not displayed, although in the debugger execution reaches handle.Finished.
public class MyThreadPool
{
private readonly Thread[] _Threads;
public delegate void ParameterizedThreadStart(object? obj);
public MyThreadPool()
{
_Threads = new Thread[1];
}
public HandleEvent QueueUserWorkItem(System.Threading.ParameterizedThreadStart callBack)
{
var thread = new Thread(callBack) { IsBackground = true };
_Threads[0] = thread;
_Threads[0].Start();
return new HandleEvent();
}
}
public class HandleEvent : EventArgs
{
public event EventHandler? Finished;
protected virtual void onFinished(object e, EventArgs s)
{
Finished?.Invoke(this, EventArgs.Empty);
}
public HandleEvent ()
{
onFinished("sddd", EventArgs.Empty);
}
}
public static class Program
{
public static void Main()
{
static void ExecuteMethod2(object execute)
{
Console.WriteLine("Hello from the thread pool.");
}
static void ExecuteMethod1(object execute)
{
Console.WriteLine("Hello from the thread pool.");
}
var thread_pool = new MyThreadPool();
var handle1 = thread_pool.QueueUserWorkItem(ExecuteMethod1);
handle1.Finished += (o, a) => { Console.WriteLine($"Done 1"); };
var handle2 = thread_pool.QueueUserWorkItem(ExecuteMethod2);
handle2.Finished += (o, a) => { Console.WriteLine($"Done 2"); };
}
}
The problem is that the onFinished method is never called. This should be called once the thread has completed execution of its callback, but it is not. For this to work the QueueUserWorkItem needs to wrap the callback in a method that does this, i.e. something like
var result = new HandleEvent();
void localExecute(object execute)
{
callBack(execute); // run the actual work
result.onFinished(); // Raise the finished method
}
var thread = new Thread(localExecute) { IsBackground = true };
_Threads[0] = thread;
_Threads[0].Start();
return result ;
However, there are other issues:
There is no actual thread pooling going on. The point of a threadpool is that threads are expensive to create, so you keep them around in a pool instead of creating new ones. The threads should be in a blocked state while in the pool, so the pool can assign the thread a task and wake it when needed.
There is no synchronization going on, so the program may very well complete before all threads are done. So you may want to return something like a ManualResetEvent that can be waited on, instead of your own custom event.
There is rarely any reason to implement your own thread pool, and doing so well is quite difficult. So I really hope you are doing this for educational purposes, and do not intend to use the result in real life.

How to keep a System.Timers.Timer stopped during ElapsedEvent

I am using System.Timers.Timer and every x seconds I need to perform some tasks in an ElapsedEvent method. While I am performing my tasks in the ElapsedEvent method, I want the timer to be stopped. However, I have another method that can start the timer, which can be called while the ElapsedEvent is running. My code looks something like this:
class MyClass {
Timer myTimer;
public MyClass {
myTimer = new System.Timers.Timer();
// init timer code here...
}
public void ElapsedEventTask(object source, ElapsedEventArgs e) {
myTimer.Enabled = false;
try
{
// do my tasks
}
catch
{
...
}
finally
{
myTimer.Enabled = true;
}
}
}
public void AnotherMethod() {
// do some things
myTimer.Enabled = true;
}
How do I prevent AnotherMethod from starting the timer while I'm completing the task in ElapsedEventTask?
You can add a variable that indicate if the task is running. Finaly to be thread safe, you need to use lock when this variable is used in with myTimer.Enabled :
class MyClass
{
object syncEnableRunning = new object();
bool running
Timer myTimer;
public void ElapsedEventTask(object source, ElapsedEventArgs e)
{
lock(syncEnableRunning)
{
running = true;
myTimer.Enabled = false;
}
try { /*do my tasks*/}
catch { ... }
finally
{
lock(syncEnableRunning)
{
myTimer.Enabled = true;
running = false;
}
}
}
public void AnotherMethod()
{
// do some things
lock(syncEnableRunning)
{
if(!running)
{
myTimer.Enabled = true;
}
}
}
}
According to the documentation the System.Timers.Timer class is not thread-safe, so it's not safe to touch its Enabled property from multiple threads without synchronization (doing so results to undefined behavior). Vernou's answer shows how to synchronize the threads by using locks, but personally I am a bit nervous with trying to enforce a non-overlapping execution policy using a mechanism that apparently was designed to be re-entrant. So my suggestion is to ditch the System.Timers.Timer, and use instead an asynchronous loop, controlled by Stephen Cleary's PauseTokenSource mechanism:
class MyClass
{
private readonly CancellationTokenSource _cts;
private readonly PauseTokenSource _pts;
public Task Completion { get; private set; }
public MyClass(TimeSpan interval)
{
_cts = new CancellationTokenSource();
_pts = new PauseTokenSource();
_pts.IsPaused = true;
Completion = Task.Run(async () =>
{
try
{
while (true)
{
await _pts.Token.WaitWhilePausedAsync(_cts.Token);
var delayTask = Task.Delay(interval, _cts.Token);
/* Do my tasks */
await delayTask;
}
}
catch (OperationCanceledException)
when (_cts.IsCancellationRequested) { } // Ignore
});
}
public void Start() => _pts.IsPaused = false;
public void Stop() => _pts.IsPaused = true;
public void Complete() => _cts.Cancel();
}
The PauseTokenSource is the controller of a PauseToken, a similar concept with the CancellationTokenSource/CancellationToken combo. The difference is that the CancellationTokenSource can be canceled only once, while the PauseTokenSource can be paused/unpaused multiple times. This class is included in the AsyncEx.Coordination package.
The MyClass exposes a Complete method that terminates the asynchronous loop, and a Completion property that can be awaited. It is a good idea to await this property before closing the program, to give to any active operation the chance to complete. Otherwise the process may be killed in the middle of a background execution, with unpredictable consequences.
I would create a one shot timer, which you then need to start again at the end of your timer function.
myTimer = new System.Timers.Timer();
myTimer.AutoReset = false;
public void ElapsedEventTask(object source, ElapsedEventArgs e) {
...
finally
{
myTimer.Start();
}
}

How do I guarantee execution of code only if and when optional main thread task and worker threads are finished?

Background:
I have an application I am developing that deals with a large number of addons for another application. One if its primary uses is to safely modify file records in files with fewer records so that they may be treated as one file (almost as if it is combing the files together into one set of records. To do this safely it keeps track of vital information about those files and changes made to them so that those changes can be undone if they don't work as expected.
When my application starts, it analyzes those files and keeps essential properties in a cache (to reduce load times). If a file is missing from the cache, the most important stuff is retrieved and then a background worker must process the file for more information. If a file that was previously modified has been updated with a new version of the file, the UI must confirm this with the user and its modification data removed. All of this information, including information on its modification is stored in the cache.
My Problem:
My problem is that neither of these processes are guaranteed to run (the confirmation window or the background file processor). If either of them run, then the cache must be updated by the main thread. I don't know enough about worker threads, and which thread runs the BackgroundWorker.RunWorkerCompleted event handler in order to effectively decide how to approach guaranteeing that the cache updater is run after either (or both) processes are completed.
To sum up: if either process is run, they both must finish and (potentially) wait for the other to be completed before running the cache update code. How can I do this?
ADJUNCT INFO (My current intervention that doesn't seem to work very well):
I have a line in the RunWorkerCompleted handler that waits until the form reference is null before continuing and exiting but maybe this was a mistake as it sometimes locks my program up.
SpinWait.SpinUntil(() => overwriteForm == null);
I haven't included any more code because I anticipate that this is more of a conceptual question than a code one. However, if necessary, I can supply code if it helps.
I think CountDownTask is what you need
using System;
using System.Threading;
public class Program
{
public class AtomicInteger
{
protected int value = 0;
public AtomicInteger(int value)
{
this.value = value;
}
public int DecrementAndGet()
{
int answer = Interlocked.Decrement(ref value);
return answer;
}
}
public interface Runnable
{
void Run();
}
public class CountDownTask
{
private AtomicInteger count;
private Runnable task;
private Object lk = new Object();
private volatile bool runnable;
private bool cancelled;
public CountDownTask(Int32 count, Runnable task)
{
this.count = new AtomicInteger(count);
this.task = task;
this.runnable = false;
this.cancelled = false;
}
public void CountDown()
{
if (count.DecrementAndGet() == 0)
{
lock (lk)
{
runnable = true;
Monitor.Pulse(lk);
}
}
}
public void Await()
{
lock (lk)
{
while (!runnable)
{
Monitor.Wait(lk);
}
if (cancelled)
{
Console.WriteLine("Sorry! I was cancelled");
}
else {
task.Run();
}
}
}
public void Cancel()
{
lock (lk)
{
runnable = true;
cancelled = true;
Monitor.Pulse(lk);
}
}
}
public class HelloWorldTask : Runnable
{
public void Run()
{
Console.WriteLine("Hello World, I'm last one");
}
}
public static void Main()
{
Thread.CurrentThread.Name = "Main";
Console.WriteLine("Current Thread: " + Thread.CurrentThread.Name);
CountDownTask countDownTask = new CountDownTask(3, new HelloWorldTask());
Thread worker1 = new Thread(() => {
Console.WriteLine("Worker 1 run");
countDownTask.CountDown();
});
Thread worker2 = new Thread(() => {
Console.WriteLine("Worker 2 run");
countDownTask.CountDown();
});
Thread lastThread = new Thread(() => countDownTask.Await());
lastThread.Start();
worker1.Start();
worker2.Start();
//countDownTask.Cancel();
Console.WriteLine("Main Thread Run");
countDownTask.CountDown();
Thread.Sleep(1000);
}
}
let me explain (but you can refer Java CountDownLatch)
1. To ensure a task must run after another tasks, we need create a Wait function to wait for they done, so I used
while(!runnable) {
Monitor.Wait(lk);
}
2. When there is a task done, we need count down, and if count down to zero (it means all of the tasks was done) we will need notify to blocked thread to wake up and process task
if(count.decrementAndGet() == 0) {
lock(lk) {
runnable = true;
Monitor.Pulse(lk);
}
}
Let read more about volatile, thanks
While dung ta van's "CountDownTask" answer isn't quite what I needed, it heavily inspired the solution below (see it for more info). Basically all I did was add some extra functionality and most importantly: made it so that each task "vote" on the outcome (true or false). Thanks dung ta van!
To be fair, dung ta van's solution DOES work to guarantee execution which as it turns out isn't quite what I needed. My solution adds the ability to make that execution conditional.
This was my solution which worked:
public enum PendingBool
{
Unknown = -1,
False,
True
}
public interface IRunnableTask
{
void Run();
}
public class AtomicInteger
{
int integer;
public int Value { get { return integer; } }
public AtomicInteger(int value) { integer = value; }
public int Decrement() { return Interlocked.Decrement(ref integer); }
public static implicit operator int(AtomicInteger ai) { return ai.integer; }
}
public class TaskElectionEventArgs
{
public bool VoteResult { get; private set; }
public TaskElectionEventArgs(bool vote) { VoteResult = vote; }
}
public delegate void VoteEventHandler(object sender, TaskElectionEventArgs e);
public class SingleVoteTask
{
private AtomicInteger votesLeft;
private IRunnableTask task;
private volatile bool runTask = false;
private object _lock = new object();
public event VoteEventHandler VoteCast;
public event VoteEventHandler TaskCompleted;
public bool IsWaiting { get { return votesLeft.Value > 0; } }
public PendingBool Result
{
get
{
if (votesLeft > 0)
return PendingBool.Unknown;
else if (runTask)
return PendingBool.True;
else
return PendingBool.False;
}
}
public SingleVoteTask(int numberOfVotes, IRunnableTask taskToRun)
{
votesLeft = new AtomicInteger(numberOfVotes);
task = taskToRun;
}
public void CastVote(bool vote)
{
votesLeft.Decrement();
runTask |= vote;
VoteCast?.Invoke(this, new TaskElectionEventArgs(vote));
if (votesLeft == 0)
lock (_lock)
{
Monitor.Pulse(_lock);
}
}
public void Await()
{
lock(_lock)
{
while (votesLeft > 0)
Monitor.Wait(_lock);
if (runTask)
task.Run();
TaskCompleted?.Invoke(this, new TaskElectionEventArgs(runTask));
}
}
}
Implementing the above solution was as simple as creating the SingleVoteTask in the UI thread and then having each thread affecting the outcome cast a vote.

Synchronization across threads / atomic checks?

I need to create an method invoker that any thread (Thread B for example sake) can call, which will execute on the main executing thread (Thead A) at a specific given point in its execution.
Example usage would be as follows:
static Invoker Invoker = new Invoker();
static void ThreadA()
{
new Thread(ThreadB).Start();
Thread.Sleep(...); // Hypothetic Alpha
Invoker.Invoke(delegate { Console.WriteLine("Action"); }, true);
Console.WriteLine("Done");
Console.ReadLine();
}
static void ThreadB()
{
Thread.Sleep(...); // Hypothetic Beta
Invoker.Execute();
}
The Invoker class looks like this:
public class Invoker
{
private Queue<Action> Actions { get; set; }
public Invoker()
{
this.Actions = new Queue<Action>();
}
public void Execute()
{
while (this.Actions.Count > 0)
{
this.Actions.Dequeue()();
}
}
public void Invoke(Action action, bool block = true)
{
ManualResetEvent done = new ManualResetEvent(!block);
this.Actions.Enqueue(delegate
{
action();
if (block) done.Set();
});
if (block)
{
done.WaitOne();
}
}
}
This works fine in most cases, although it won't if, for any reason, the execution (and therefore the Set) is done before the WaitOne, in which case it will just freeze (it allows for the thread to proceed, then blocks). That could be reproduced if Alpha >> Beta.
I can use booleans and whatnot, but I'm never getting a real atomic safety here. I tried some fixes, but they wouldn't work in the case where Beta >> Alpha.
I also thought of locking around both the Invoker.Execute and Invoker.Invoke methods so that we are guaranteed that the execution does not occur between enqueing and waiting. However, the problem is that the lock also englobes the WaitOne, and therefore never finishes (deadlock).
How should I go about getting absolute atomic safety in this paradigm?
Note: It really is a requirement that I work with this design, from external dependencies. So changing design is not a real option.
EDIT: I did forget to mention that I want a blocking behaviour (based on bool block) until the delegate is executed on the Invoke call.
Use a Semaphore(Slim) instead of the ManualResetEvent.
Create a semaphore with an maximum count of 1, call WaitOne() in the calling thread, and call Release() in the delegate.
If you've already called Release(), WaitOne() should return immediately.
Make sure to Dispose() it when you're done, preferably in a using block.
If block is false, you shouldn't create it in the first place (although for SemaphoreSlim, that's not so bad).
You can use my technique:
public void BlockingInvoke(Action action)
{
volatile bool isCompleted = false;
volatile bool isWaiting = false;
ManualResetEventSlim waiter = new ManualResetEventSlim();
this.Actions.Enqueue(delegate
{
action();
isCompleted = true;
Thread.MemoryBarrier();
if (!isWaiting)
waiter.Dispose();
else
waiter.Set();
});
isWaiting = true;
Thread.MemoryBarrier();
if (!isCompleted)
waiter.Wait();
waiter.Dispose();
}
Untested
I'm answering only to show the implementation SLaks described and my solution to ensure proper and unique disposal with locks. It's open to improvement and criticism, but it actually works.
public class Invoker
{
private Queue<Action> Actions { get; set; }
public Invoker()
{
this.Actions = new Queue<Action>();
}
public void Execute()
{
while (this.Actions.Count > 0)
{
this.Actions.Dequeue()();
}
}
public void Invoke(Action action, bool block = true)
{
if (block)
{
SemaphoreSlim semaphore = new SemaphoreSlim(1);
bool disposed = false;
this.Actions.Enqueue(delegate
{
action();
semaphore.Release();
lock (semaphore)
{
semaphore.Dispose();
disposed = true;
}
});
lock (semaphore)
{
if (!disposed)
{
semaphore.Wait();
semaphore.Dispose();
}
}
}
else
{
this.Actions.Enqueue(action);
}
}
}

How do I wait for a C# event to be raised?

I have a Sender class that sends a Message on a IChannel:
public class MessageEventArgs : EventArgs {
public Message Message { get; private set; }
public MessageEventArgs(Message m) { Message = m; }
}
public interface IChannel {
public event EventHandler<MessageEventArgs> MessageReceived;
void Send(Message m);
}
public class Sender {
public const int MaxWaitInMs = 5000;
private IChannel _c = ...;
public Message Send(Message m) {
_c.Send(m);
// wait for MaxWaitInMs to get an event from _c.MessageReceived
// return the message or null if no message was received in response
}
}
When we send messages, the IChannel sometimes gives a response depending on what kind of Message was sent by raising the MessageReceived event. The event arguments contain the message of interest.
I want Sender.Send() method to wait for a short time to see if this event is raised. If so, I'll return its MessageEventArgs.Message property. If not, I return a null Message.
How can I wait in this way? I'd prefer not to have do the threading legwork with ManualResetEvents and such, so sticking to regular events would be optimal for me.
Use a AutoResetEvent.
Gimme a few minutes and I'll throw together a sample.
Here it is:
public class Sender
{
public static readonly TimeSpan MaxWait = TimeSpan.FromMilliseconds(5000);
private IChannel _c;
private AutoResetEvent _messageReceived;
public Sender()
{
// initialize _c
this._messageReceived = new AutoResetEvent(false);
this._c.MessageReceived += this.MessageReceived;
}
public Message Send(Message m)
{
this._c.Send(m);
// wait for MaxWaitInMs to get an event from _c.MessageReceived
// return the message or null if no message was received in response
// This will wait for up to 5000 ms, then throw an exception.
this._messageReceived.WaitOne(MaxWait);
return null;
}
public void MessageReceived(object sender, MessageEventArgs e)
{
//Do whatever you need to do with the message
this._messageReceived.Set();
}
}
Have you tried assigning the function to call asynchronously to a delegate, then invoking the mydelegateinstance.BeginInvoke?
Linky for reference.
With the below example, just call
FillDataSet(ref table, ref dataset);
and it'll work as if by magic. :)
#region DataSet manipulation
///<summary>Fills a the distance table of a dataset</summary>
private void FillDataSet(ref DistanceDataTableAdapter taD, ref MyDataSet ds) {
using (var myMRE = new ManualResetEventSlim(false)) {
ds.EnforceConstraints = false;
ds.Distance.BeginLoadData();
Func<DistanceDataTable, int> distanceFill = taD.Fill;
distanceFill.BeginInvoke(ds.Distance, FillCallback<DistanceDataTable>, new object[] { distanceFill, myMRE });
WaitHandle.WaitAll(new []{ myMRE.WaitHandle });
ds.Distance.EndLoadData();
ds.EnforceConstraints = true;
}
}
/// <summary>
/// Callback used when filling a table asynchronously.
/// </summary>
/// <param name="result">Represents the status of the asynchronous operation.</param>
private void FillCallback<MyDataTable>(IAsyncResult result) where MyDataTable: DataTable {
var state = result.AsyncState as object[];
Debug.Assert((state != null) && (state.Length == 2), "State variable is either null or an invalid number of parameters were passed.");
var fillFunc = state[0] as Func<MyDataTable, int>;
var mre = state[1] as ManualResetEventSlim;
Debug.Assert((mre != null) && (fillFunc != null));
int rowsAffected = fillFunc.EndInvoke(result);
Debug.WriteLine(" Rows: " + rowsAffected.ToString());
mre.Set();
}
Perhaps your MessageReceived method should simply flag a value to a property of your IChannel interface, while implementing the INotifyPropertyChanged event handler, so that you would be advised when the property is changed.
By doing so, your Sender class could loop until the max waiting time is elapsed, or whenever the PropertyChanged event handler occurs, breaking the loop succesfully. If your loop doesn't get broken, then the message shall be considered as never received.
Useful sample with AutoResetEvent:
using System;
using System.Threading;
class WaitOne
{
static AutoResetEvent autoEvent = new AutoResetEvent(false);
static void Main()
{
Console.WriteLine("Main starting.");
ThreadPool.QueueUserWorkItem(
new WaitCallback(WorkMethod), autoEvent);
// Wait for work method to signal.
autoEvent.WaitOne();
Console.WriteLine("Work method signaled.\nMain ending.");
}
static void WorkMethod(object stateInfo)
{
Console.WriteLine("Work starting.");
// Simulate time spent working.
Thread.Sleep(new Random().Next(100, 2000));
// Signal that work is finished.
Console.WriteLine("Work ending.");
((AutoResetEvent)stateInfo).Set();
}
}
WaitOne is really the right tool for this job. In short, you want to wait between 0 and MaxWaitInMs milliseconds for a job to complete. You really have two choices, poll for completion or synchronize the threads with some construct that can wait an arbitrary amount of time.
Since you're well aware of the right way to do this, for posterity I'll post the polling version:
MessageEventArgs msgArgs = null;
var callback = (object o, MessageEventArgs args) => {
msgArgs = args;
};
_c.MessageReceived += callback;
_c.Send(m);
int msLeft = MaxWaitInMs;
while (msgArgs == null || msLeft >= 0) {
Thread.Sleep(100);
msLeft -= 100; // you should measure this instead with say, Stopwatch
}
_c.MessageRecieved -= callback;

Categories

Resources