Delegate.BeginInvoke Callback Blocking Calling Thread? - c#

I'm not really sure where to look with this problem as I'm not particularly familiar with asynchronous programming. I have a loop which invokes a delegate's BeginInvoke method. When the delegate's callback is executed the loop ceases to execute (it shouldn't). I'm guessing that somehow the thread it's running on is being blocked but I really don't know for sure. Here's a simplified version of the code:
public class TestClass
{
private readonly IService service;
private delegate void TestDelegate();
private bool conditionIsMet = true;
public TestClass( IService service )
{
this.service = service;
}
public void PerformTask()
{
while ( conditionIsMet )
{
var testDelegate = new TestDelegate( service.DoSomething );
testDelegate.BeginInvoke( TestCallback, null );
Thread.Sleep( 1 );
}
}
private void TestCallback( IAsyncResult result )
{
var asyncResult = ( AsyncResult ) result;
var testDelegate = ( TestDelegate ) asyncResult.AsyncDelegate;
testDelegate.EndInvoke( asyncResult );
// After exiting this method the loop in PerformTask() ceases to execute.
// Is it being blocked here somehow?
}
}
In practice there is a bit more to the code but the essential components involved are all here so far as I can tell. In the code sample above I've put a comment in there to indicate the last place the code executes (in the VS debugger, anyway).
I assume that I'm making some sort of fundamental error in the way I'm doing the delegate async invocation but I can't find any docs that explain it to me. Any idea why this is happening?
UPDATE
As part of further testing, I tried this without the EndInvoke call (I know, bad idea in practice) but there was no change in behaviour - it still failed to continue executing the loop.

It works ok for me I think. Are you running it in a console application?
You would need to stop that exiting.
class Program
{
static void Main(string[] args)
{
TestClass t = new TestClass(new Service());
t.PerformTask();
Console.ReadKey();
}
}
public class Service : IService
{
public void DoSomething()
{
Console.WriteLine("Doing something");
}
}
public class TestClass
{
private readonly IService service;
private delegate void TestDelegate();
private bool conditionIsMet = true;
public TestClass(IService service)
{
this.service = service;
}
public void PerformTask()
{
while (conditionIsMet)
{
var testDelegate = new TestDelegate(service.DoSomething);
testDelegate.BeginInvoke(TestCallback, null);
Thread.Sleep(1);
}
}
private void TestCallback(IAsyncResult result)
{
var asyncResult = (AsyncResult)result;
var testDelegate = (TestDelegate)asyncResult.AsyncDelegate;
testDelegate.EndInvoke(asyncResult);
// After exiting this method the loop in PerformTask() ceases to execute.
// Is it being blocked here somehow?
}
}
public interface IService
{
void DoSomething();
}

Related

Convert C# Console>Service? How to retain dictionary when Class calls itself?

I'm attempting to transform a simple console application so that it may be used as a service using a nested Service class (relevant code below). The intent is to create a service to perform the actions within the Run method more-or-less at a set interval (eventually, ~hourly).
In short, the Service's OnStart calls my own Start method once, which creates a timer. Inside the timer, I'm creating an instance of the Program class, and performing the Run method till it finishes. I believe this is a valid implementation of what I want that doesn't leave resources outstanding.
Part of what the Run method does is build a dictionary of actions it was unable to perform on the file system, and I would like to retain the dictionary in subsequent calls to Run in order to attempt these actions again, if possible. What would be the best implementation to accomplish this? I'm a bit green and not terribly confident I'm doing things correctly, but I'm attempting to get up to speed as quickly as possible, so any assistance is appreciated.
partial class Program{
static object timerLck = new object();
public class Service : ServiceBase{
public Service(){
ServiceName = Program.ServiceName;
}
protected override void OnStart(string[] args){
Program.Start(args);
}
protected override void OnStop(){
Program.Stop();
}
}
static void Main(string[] args){
if (!Environment.UserInteractive)
using (var service = new Service())
ServiceBase.Run(service);
else{
Start(args);
Stop();
}
}
private static void Start(string[] args){
Timer t = new Timer(CallTimer, null, 0, 50000);
Console.ReadKey();
}
private static void Stop(){
//???
}
static void CallTimer(object state){
bool Lock = false;
try{
Lock = Monitor.TryEnter(timerLck);
if (Lock){
Program Prg = new Program()
var task = Task.Run((Func<Task<int>>)Prg.Run);
task.Wait();
}
}
finally{
if (Lock) Monitor.Exit(timerLck);
}
}
//Perform the repeated actions here
private async Task<int> Run()
{
Dictionary<string, Metadata> d = new Dictionary<string, Metadata>();
//...
return 0;
}
}
You can just have Run accept a Dictionary as a parameter and return the populated Dictionary.
private async Task<Dictionary<string, Metadata>> Run(Dictionary<string,
Metadata> previousErrors)
{
Dictionary<string, Metadata> d = new Dictionary<string, Metadata>();
//...
return d;
}
Then set a property PreviousErrors on your Program class to the returned Dictionary.
static void CallTimer(object state){
bool Lock = false;
try{
Lock = Monitor.TryEnter(timerLck);
if (Lock){
Program Prg = new Program()
var task = Task.Run(()=>Run(PreviousErrors));
PreviousErrors = task.Result;
}
}
finally{
if (Lock) Monitor.Exit(timerLck);
}
}
Note, that I'm only addressing your question not the quality of the rest of the code. It could do with improvements that are outside of the scope of your question.

API methods must wait until critical method is done

I have MVC API controller.
One method in this controller is critical.
This mean that all other API methods must wait util this method is done.
My basic idea is to block threads in constructor.
But I am not sure if this is so smart?
public class TestApi : Controller
{
private static bool wait = false;
public TestApi()
{
// wait if critical method is working.
while (wait)
{
System.Threading.Thread.Sleep(100);
}
}
[HttpPost]
public void PostCriticalMethod()
{
try
{
wait = true;
// do critical work
}
finally
{
wait = false;
}
}
// Many non critical API methods...
}
Solution two:
public class TestApi : Controller
{
private static bool wait = false;
private static AutoResetEvent waitHandle = new AutoResetEvent(false);
public TestApi()
{
// wait if critical method is working.
if (wait) waitHandle.WaitOne();
}
[HttpPost]
public void PostCriticalMethod()
{
try
{
wait = true;
// do critical work
}
finally {
waitHandle.Set();
wait = false;
}
}
// Many non critical API methods...
}
My solution (This is async version, but non async is even simpler):
In base class (common for all controllers) I add method BlockOtherRequestsBeforeExecute
private static readonly SemaphoreSlim semaphoreInit = new SemaphoreSlim(1, 1);
protected async Task BlockOtherRequestsBeforeExecute(Func<Task> criticalAction)
{
await semaphoreInit.WaitAsync();
try
{
await criticalAction();
}
finally
{
semaphoreInit.Release();
}
}
Then I can call method in secure way if I need to:
await BlockOtherRequestsBeforeExecute(async () => await RestoreDatabase());
Important part is that semaphoreInit must be used in all critical places.
This can be done in constructor of base class, and then all API-s are blocked until critical action is not finished.

Multiple timer/callbacks — best approach to prevent duplicates and to monitor them

I have a c# console, that I have made into a Windows service, which I would like to run reliably and constantly.
I want to prevent overlap of the same timer firing again
I want to prevent different timers trying to use the same resource at once
I want to be able to monitor the timers and interact with then.
It has a few aspects to it. Each runs very regularly. I have previously read about TaskScheduler vs Windows Service running this kind of thing, and have opted for this approach because something is running almost constantly.
TaskType1
TaskType2
TaskType3
TaskType4
I'm using timer callbacks, each with their own, similar to this simplified version:
class Program
{
static PollingService _service;
static void Main()
{
_service = new PollingService();
TimerCallback tc1 = _service.TaskType1;
TimerCallback tc2 = _service.TaskType2;
TimerCallback tc3 = _service.TaskType3A;
TimerCallback tc4 = _service.TaskType3B;
Timer t1 = new Timer(tc1, null, 1000, 5000);
Timer t2 = new Timer(tc2, null, 2000, 8000);
Timer t3 = new Timer(tc3, null, 3000, 11000);
Timer t4 = new Timer(tc4, null, 4000, 13000);
Console.WriteLine("Press Q to quit");
while (Console.ReadKey(true).KeyChar != 'q')
{
}
}
}
class PollingService
{
public void TaskType1(object state)
{
for (int i = 1; i <= 10; i++)
{
Console.WriteLine($"TaskOne numbering {i}");
Thread.Sleep(100);
}
}
public void TaskType2(object state)
{
for (int i = 10; i <= 100; i++)
{
Console.WriteLine($"TaskTwo numbering {i}");
Thread.Sleep(100);
}
}
public void TaskType3A(object state)
{
Increment(200000000);
}
public void TaskType3B(object state)
{
Increment(40000);
}
private void Increment(int startNumber)
{
for (int i = startNumber; i <= startNumber + 1000; i++)
{
Console.WriteLine($"Private {startNumber} numbering {i}");
Thread.Sleep(5);
}
}
}
1 Firstly I want to ensure these don't get tied up with each other when one sometimes runs long.
Eg. If Task one takes 20 seconds to run sometimes, I want to prevent a duplicate timer while the previous might still be running, the same for all of the timers infact. Eg. if t2 is running for a little longer than usual then don't start another. I've read a little about if (Monitor.TryEnter(lockObject)), is that the best way to handle that requirement?
2 Secondly if they both access the same resource (in my case an EF context), such that t3 is already using it, and t4 tries to do so. Is there a way of asking the timer to wait until the other finishes?
3 Lastly is there a way I can monitor these timer/callbacks? I'd like to provide an UI to see the state of this when I have it running as a windows service. My endgame there is to provide a UI that users can see if a task is running, and if not then trigger it on demand if one isn't set to run for a little while. But in the same breath, not create a duplicate while one is running.
I have wondered whether I should've asked these as separate questions, but they seem so entwined with the decision of each other.
If you have to make sure that each thread doesn't have any overlap, you can use the Timer.Change(int, int) method to stop executing at the start of the callback, and then resume it at the end of the callback. You can also do some magic with a ManualResetEvent for each thread but it'll get messy.
I'm not a fan of timers for threading and try to avoid them whenever I can. If you can sacrifice the "each thread must run after n seconds", do it. Use tasks with a cancellation token instead, it will solve your overlap problem. For example:
A.
public class Foo
{
private CancellationTokenSource _cts;
//In case you care about what tasks you have.
private List< Task > _tasks;
public Foo()
{
this._cts = new CancellationTokenSource();
this._tasks.Add(Task.Factory.StartNew(this.Method1, this._cts.Token));
this._tasks.Add(Task.Factory.StartNew(this.Method2, this._cts.Token));
this._tasks.Add(Task.Factory.StartNew(this.Method3, this._cts.Token));
this._tasks.Add(Task.Factory.StartNew(this.Method4, this._cts.Token));
}
private void Method1(object state)
{
var token = (CancellationToken) state;
while ( !token.IsCancellationRequested )
{
//do stuff
}
}
private void Method2(object state)
{
var token = (CancellationToken)state;
while (!token.IsCancellationRequested)
{
//do stuff
}
}
private void Method3(object state)
{
var token = (CancellationToken)state;
while (!token.IsCancellationRequested)
{
//do stuff
}
}
private void Method4(object state)
{
var token = (CancellationToken)state;
while (!token.IsCancellationRequested)
{
//do stuff
}
}
public void StopExecution()
{
this._cts.Cancel();
}
}
An EF context will throw an exception if used by more than one thread at a time. There is a way to synchronize it, using lock. It would look something like this, given the example above:
B.
public class Foo
{
private object _efLock;
public Foo()
{
this._efLock = new object();
}
.
.
.
private void MethodX(object state)
{
var token = (CancellationToken)state;
while (!token.IsCancellationRequested)
{
lock(this._efLock)
{
using(.......
}
}
}
}
You'll have to do that in each thread that accesses your EF context. Keep in mind that, again, maintenance gets annoying because of the cognitive load that goes with complex lock scenarios.
I recently developed an application in which I needed multiple threads to access the same EF context. As I mentioned above, the locking got to be too much (and there was a performance requirement), so I devised a solution where each thread adds its object to a common queue, and a separate thread does nothing but pull data from the queue and call into EF. That way the EF context is only ever accessed by one thread. Problem solved. Here is what that would look like given the sample above:
C.
public class Foo
{
private struct InternalEFData
{
public int SomeProperty;
}
private CancellationTokenSource _dataCreatorCts;
private CancellationTokenSource _efCts;
//In case you care about what tasks you have.
private List< Task > _tasks;
private Task _entityFrameworkTask;
private ConcurrentBag< InternalEFData > _efData;
public Foo()
{
this._efData = new ConcurrentBag< InternalEFData >();
this._dataCreatorCts = new CancellationTokenSource();
this._efCts = new CancellationTokenSource();
this._entityFrameworkTask = Task.Factory.StartNew(this.ProcessEFData, this._efCts.Token);
this._tasks.Add(Task.Factory.StartNew(this.Method1, this._dataCreatorCts.Token));
this._tasks.Add(Task.Factory.StartNew(this.Method2, this._dataCreatorCts.Token));
.
.
.
}
private void ProcessEFData(object state)
{
var token = (CancellationToken) state;
while ( !token.IsCancellationRequested )
{
InternalEFData item;
if (this._efData.TryTake(out item))
{
using ( var efContext = new MyDbContext() )
{
//Do processing.
}
}
}
}
private void Method1(object state)
{
var token = (CancellationToken) state;
while ( !token.IsCancellationRequested )
{
//Get data from whatever source
this._efData.Add(new InternalEFData());
}
}
private void Method2(object state)
{
var token = (CancellationToken) state;
while ( !token.IsCancellationRequested )
{
//Get data from whatever source
this._efData.Add(new InternalEFData());
}
}
public void StopExecution()
{
this._dataCreatorCts.Cancel();
this._efCts.Cancel();
}
}
When it comes to reading data from executing threads, I generally use a SynchronizationContext. I don't know if it's the right object to use and someone else can probably comment on that. Create a Synchronization object, pass it to your threads and have them update it with the necessary data and post it to your UI/Console thread:
D.
public struct SyncObject
{
public int SomeField;
}
public delegate void SyncHandler(SyncObject s);
public class Synchronizer
{
public event SyncHandler OnSynchronization;
private SynchronizationContext _context;
public Synchronizer()
{
this._context = new SynchronizationContext();
}
public void PostUpdate(SyncObject o)
{
var handleNullRefs = this.OnSynchronization;
if ( handleNullRefs != null )
{
this._context.Post(state => handleNullRefs((SyncObject)state), o);
}
}
}
public class Foo
{
private Synchronizer _sync;
public Foo(Synchronizer s)
{
this._sync = s;
}
private void Method1(object state)
{
var token = (CancellationToken) state;
while ( !token.IsCancellationRequested )
{
//do things
this._sync.PostUpdate(new SyncObject());
}
}
}
Again, that's how I do it, I don't know if it's the proper way.
basically, yes, or AutoResetEvent
you can stop it, wait for the resource to free up, and then restart it
keep a list of states associated with your timers, and update those states from the timers (set to running when starting, set to waiting when done, or something along these lines)
1: Likely the best is not to do anything in the timers but stat a task - IF any WHEN a flag is set or not set. Look for interlocked (the class) on how to implement that without locking.
2: Monitor. But seriously, why do they share an EF contect?
3: Sure. Create performance counters. Monitor them. The API is in windows for many many years.

Unit testing a background thread with an interface

I have created a class, SenderClass, which will start and run a background worker from its constructor.
The method, RunWorker(), runs is a while(true) loop which will pop elements from a queue, send them through the method SendMessage(), and sleep for a small amount of time to allow new elements to be added to the queue.
Here lies the problem: How do I test the method that sends the element from the queue, without exposing it to those who uses the class?
Implementation:
public class SenderClass : ISenderClass
{
private Queue<int> _myQueue = new Queue<int>();
private Thread _worker;
public SenderClass()
{
//Create a background worker
_worker = new Thread(RunWorker) {IsBackground = true};
_worker.Start();
}
private void RunWorker() //This is the background worker's method
{
while (true) //Keep it running
{
lock (_myQueue) //No fiddling from other threads
{
while (_myQueue.Count != 0) //Pop elements if found
SendMessage(_myQueue.Dequeue()); //Send the element
}
Thread.Sleep(50); //Allow new elements to be inserted
}
}
private void SendMessage(int element)
{
//This is what we want to test
}
public void AddToQueue(int element)
{
Task.Run(() => //Async method will return at ones, not slowing the caller
{
lock (_myQueue) //Lock queue to insert into it
{
_myQueue.Enqueue(element);
}
});
}
}
Wanted interface:
public interface ISenderClass
{
void AddToQueue(int element);
}
Needed interface for test purpose:
public interface ISenderClass
{
void SendMessage(int element);
void AddToQueue(int element);
}
There's a very simple solution, saying I have created my class incorrect due to the Single Responsability Principle, and my class' purpose is not to send messages, but actually run what sends them.
What I should have, is another class, TransmittingClass, which exposes the method SendMessage(int) through its own interface.
This way I can test that class, and SenderClass should just call the method through that interface.
But what other options do I have with the current implementation?
I can make all private methods I wish to test (all of them) have a [assembly:InternalsVisibleTo("MyTests")], but does a third option exist?
Send message logic should be implemented in a separate class with a separate interface. This class should take the new class as a dependency. You can test the new class separately.
public interface IMessageQueue
{
void AddToQueue(int element);
}
public interface IMessageSender
{
void SendMessage(object message);
}
public class SenderClass : IMessageQueue
{
private readonly IMessageSender _sender;
public SenderClass(IMessageSender sender)
{
_sender = sender;
}
public void AddToQueue(int element)
{
/*...*/
}
private void SendMessage()
{
_sender.SendMessage(new object());
}
}
public class DummyMessageSender : IMessageSender
{
//you can use this in your test harness to check for the messages sent
public Queue<object> Messages { get; private set; }
public DummyMessageSender()
{
Messages = new Queue<object>();
}
public void SendMessage(object message)
{
Messages.Enqueue(message);
//obviously you'll need to do some locking here too
}
}
Edit
To address your comment, here is an implementation using Action<int>. This allows you to define your message sending action in your test class to mock the SendMessage method without worrying about creating another class. (Personally, I'd still prefer to define the classes/interfaces explicitly).
public class SenderClass : ISenderClass
{
private Queue<int> _myQueue = new Queue<int>();
private Thread _worker;
private readonly Action<int> _senderAction;
public SenderClass()
{
_worker = new Thread(RunWorker) { IsBackground = true };
_worker.Start();
_senderAction = DefaultMessageSendingAction;
}
public SenderClass(Action<int> senderAction)
{
//Create a background worker
_worker = new Thread(RunWorker) { IsBackground = true };
_worker.Start();
_senderAction = senderAction;
}
private void RunWorker() //This is the background worker's method
{
while (true) //Keep it running
{
lock (_myQueue) //No fiddling from other threads
{
while (_myQueue.Count != 0) //Pop elements if found
SendMessage(_myQueue.Dequeue()); //Send the element
}
Thread.Sleep(50); //Allow new elements to be inserted
}
}
private void SendMessage(int element)
{
_senderAction(element);
}
private void DefaultMessageSendingAction(int item)
{
/* whatever happens during sending */
}
public void AddToQueue(int element)
{
Task.Run(() => //Async method will return at ones, not slowing the caller
{
lock (_myQueue) //Lock queue to insert into it
{
_myQueue.Enqueue(element);
}
});
}
}
public class TestClass
{
private SenderClass _sender;
private Queue<int> _messages;
[TestInitialize]
public void SetUp()
{
_messages = new Queue<int>();
_sender = new SenderClass(DummyMessageSendingAction);
}
private void DummyMessageSendingAction(int item)
{
_messages.Enqueue(item);
}
[TestMethod]
public void TestMethod1()
{
//This isn't a great test, but I think you get the idea
int message = 42;
_sender.AddToQueue(message);
Thread.Sleep(100);
CollectionAssert.Contains(_messages, 42);
}
}
It looks like SenderClass should not perform any sending at all. It should simply maintain the queue. Inject an Action<int> through the constructor that does the sending. That way you can move SendMessage somewhere else and call it however you like.
As an added benefit your test of SendMessage is not cluttered with queue management.
Seeing your edit you don't seem to like this approach and you don't seem to like the InternalsVisibleTo approach either. You could expose SendMessage through a separate interface and implement that interface explicitly. That way SendMessage is still callable through that interface but by default it is not accessible without some casting contortions. It also does not show up in the intellisense autocomplete list.

Why does asynchronous delegate method require calling EndInvoke?

Why does the delegate need to call the EndInvoke before the method fires? If i need to call the EndInvoke (which blocks the thread) then its not really an asynchronous call is it?
Here is the code im trying to run.
class Program
{
private delegate void GenerateXmlDelegate();
static void Main(string[] args)
{
GenerateXmlDelegate worker = new GenerateXmlDelegate(GenerateMainXml);
IAsyncResult result = worker.BeginInvoke(null, null);
}
private static void GenerateMainXml()
{
Thread.Sleep(10000);
Console.WriteLine("GenerateMainXml Called by delegate");
}
}
The reason you need to call EndInvoke is to avoid memory leaks; .Net will store information about the function's result (or exception) until you call EndInvoke.
You can call EndInvoke in the completion handler that you give to BeginInvoke and retain the asyncronous nature.
EDIT:
For example:
class Program {
private delegate void GenerateXmlDelegate();
static void Main(string[] args) {
GenerateXmlDelegate worker = new GenerateXmlDelegate(GenerateMainXml);
IAsyncResult result = worker.BeginInvoke(delegate {
try {
worker.EndInvoke();
} catch(...) { ... }
}, null);
}
private static void GenerateMainXml() {
Thread.Sleep(10000);
Console.WriteLine("GenerateMainXml Called by delegate");
}
}
If you want to fire an async call and forget about it, you can use the ThreadPool, like this:
ThreadPool.QueueUserWorkItem(delegate { GenerateMainXml(); });
As SLaks said, EndInvoke insures against memory leaks.
BeginInvoke is still asynchronous; consider the following code:
static void Main() {
Func<double> slowCalculator = new Func<double>(PerformSlowCalculation);
IAsyncResult slowCalculation = slowCalculator.BeginInvoke(null, null);
// lots of stuff to do while slowCalculator is doing its thing
Console.WriteLine("Result is {0}", slowCalculator.EndInvoke(slowCalculation));
}
static double PerformSlowCalculation() {
double result;
// lots and lots of code
return result;
}
If this code were written without the BeginInvoke/EndInvoke calls, PerformSlowCalculation would have to finish before Main could do the rest of its "lots of stuff"; this way, the two can be happening at the same time.
Now, in your example using a GenerateXmlDelegate, you still need EndInvoke even though you're not returning anything. The way to do this is:
static void Main(string[] args) {
GenerateXmlDelegate worker = new GenerateXmlDelegate(GenerateMainXml);
IAsyncResult result = worker.BeginInvoke(GenerateXmlComplete, null);
}
private static void GenerateXmlComplete(IAsyncResult result) {
AsyncResult realResult = result as AsyncResult;
GenerateXmlDelegate worker = result.AsyncDelegate as GenerateXmlDelegate;
worker.EndInvoke();
}

Categories

Resources