Use actions inside AsyncCallback - c#

My class does the following (simplified):
public void Startup(Action myAction)
{
_myAction = myAction;
}
private void EstablishApplicationEndpoint()
{
...
ApplicationEndpoint.BeginEstablish(OnApplicationEndpointEstablishCompleted, null);
}
private void OnApplicationEndpointEstablishCompleted(IAsyncResult result)
{
try
{
...
_myAction();
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
The BeginEstablish method takes an AsyncCallback as first parameter.
However myAction is never executed (I use the class from a console application). The action should output something to the console and read a line, but the console is closed immediately.
My console application:
static void Main(string[] args)
{
StartPlatform();
}
private static void StartPlatform()
{
...
_platformController.Startup(SendContext);
}
private static void SendContext()
{
Console.WriteLine("Press ENTER to send context");
Console.ReadLine();
...
}
As the console can't know that a ReadLine- call will come at some time it closes automatically. How can I prevent to do so?

You are using the 'Asynchronous Programming Model (APM)' pattern:
https://msdn.microsoft.com/en-us/library/ms228963(v=vs.110).aspx
This model is typified by the use of Begin and End methods.
Note that when a Begin method (such as your BeginEstablish) is invoked, the work denoted by the callback method is scheduled to occur on a separate (background) thread, and program control is returned immediately in the main thread.
The assumption is that other computation can occur on the main thread, at some point the callback will have completed on the background thread, and the results of the background thread will then be re-joined to the main thread.
The mechanism for re-joining is a call to a corresponding End method (so in your case, a call to EndEstablish). As such, to prevent your console application from exiting due to the immediate return of control from the call to BeginEstablish, you need to do the following:
Maintain a reference to the the IAsyncResult object that is returned from the Begin call
At some point in the code path following the call to Begin, call the corresponding End, passing in the IAsyncResult object obtained from the call to Begin
Optionally use the second parameter to the Begin call to manage state
What this might look like is:
private IAsyncResult EstablishApplicationEndpoint()
{
...
return ApplicationEndpoint.BeginEstablish(OnApplicationEndpointEstablishCompleted, null);
}
...
private static void StartPlatform()
{
...
_platformController.Startup(SendContext);
var asyncResult = _platformController.EstablishApplicationEndpoint();
// Do other things
// Re-join the callback
ApplicationEndpoint.EndEstablish(asyncResult);
}
Keep in mind that if the callback has not yet completed by the time End is called, End will at that point block and wait for the callback to complete.
Since your callback is interacting with the Console, I suspect this will mean the call to End will be blocking in your case.

Related

How to execute some code when a block exits due to "await"?

tldr: Is there a way to execute some code when an "await" causes a method call to return?
Suppose I log entry and exit of C# methods with an object whose Dispose() method logs the method's exit. For example
void DoWhatever()
{
using (LogMethodCall("DoWhatever")
{
// do whatever
}
}
That is, the method LogMethodCall() logs "DoWhatever entered" and then returns an object of type CallEnder whose Dispose() method logs "DoWhatever exiting". That works fine until await is used. For example...
async Task DoWhatever()
{
using (LogMethodCall("DoWhatever")
{
// do first part.
await Something();
// do second part.
}
}
The above code returns a Task to the caller when it hits the await, and the rest of the code (including the call to CallEnder.Dispose()) runs in that Task. My problem is that I want to log "DoWhatever exiting" when the await triggers the actual return, and not when CallEnder.Dispose() is finally called.
Is there a way to do that? Is there something like an event that's raised when await causes DoWhatever() to return? Maybe something to do with ExecutionContext or CallContext or TaskScheduler?
Note that I need to keep the "using (some_object)" pattern described in the above code. That pattern works well to log entry and exit of a block. I can change the implementation of some_object to detect when control returns from DoWhatever() to its caller, but I'd prefer not to change the implementation of DoWhatever(). Although I could if there's no other way.
ETA further clarification: I want to
Log when control exits from DoWhatever() and returns to its caller,
whether that's due to the await or due to the "natural" exit from
DoWhatever().
Do it in the same thread that called DoWhatever().
Preferably do it via the "using" clause shown above because that
pattern is already used in many places and works perfectly without
await.
Surprisingly it can be done, using AsyncLocal. AsyncLocal is like ThreadLocal except it flows through async code which might switch threads. It has a constructor which allows you to listen for value changes, and it even tells you the reason value has changed. It can be changed either because you explicitly set Value or if async context switch happens (in this case, Value changes to null/default when control leaves, and it changes back to original value when control returns). This allows us to detect when first await is reached, and not just first await but await that will introduce context switch (so, await Task.CompletedTask will not trigger context switch for example). So on first such switch Task will be returned back to caller.
Here is sample code:
public class Program {
public static void Main() {
var task = Test();
Console.WriteLine("Control flow got out of Test");
task.Wait();
}
static async Task Test() {
using (LogMethodCall()) {
await Task.Delay(1000);
Console.WriteLine("Finished using block");
}
}
static IDisposable LogMethodCall([CallerMemberName] string methodName = null) {
return new Logger(methodName);
}
private class Logger : IDisposable {
private readonly string _methodName;
private AsyncLocal<object> _alocal;
private bool _disposed;
public Logger(string methodName) {
Console.WriteLine($"{methodName} entered");
_methodName = methodName;
_alocal = new AsyncLocal<object>(OnChanged);
_alocal.Value = new object();
}
private void OnChanged(AsyncLocalValueChangedArgs<object> args) {
if (_disposed)
return;
// this property tells us that value changed because of context switch
if (args.ThreadContextChanged) {
Dispose();
}
}
public void Dispose() {
// prevent multiple disposal
if (_disposed)
return;
_disposed = true;
_alocal = null;
Console.WriteLine($"{_methodName} exited");
}
}
}
It outputs:
Test entered
Test exited
Control flow got out of Test
Finished using block
You can use the same code for regular functions too, because in them async local will never change and so dispose will happen as usual in the end of using block.
If you want to log when Something finished any synchronous actions and returns a Task, this is easy:
var task = Something();
/* log as you like */
await task;

Is there a way to abort a thread and then open it again with a new variable?

I want to open a thread to do the things it needs to do until a new command is given by the user. Then this thread should either close or receive a new command.
I have seen many posts that sending a variable to a running thread is hard, that is why I decided to kill the thread and start it again with the new variable.
I used the following post: https://stackoverflow.com/a/1327377 but without success. When I start the thread again (after it has done abort()) it gives me an exception: System.Threading.ThreadStateException.
private static Thread t = new Thread(Threading);
private static bool _running = false;
static void Main(string[] args)
{
[get arg]
if (CanRedo(arg))
{
if (t.IsAlive)
{
_running = false;
t.Interrupt();
if (t.Join(2000)) // with a '!' like in the post, abort() would not be called
{
t.Abort();
}
}
_running = true;
t.Start(arg); // gives System.Threading.ThreadStateException
}
}
private static void Threading(object obj)
{
_stopped = false;
string arg = obj.ToString();
while(_running)
{
if (bot._isDone)
{
ExecuteInstruction(arg);
}
}
}
What am I doing wrong?
I'm going to guess that you don't literally mean to abort the thread and start that same thread again. That's because if we start a thread to do some work we don't care which thread it is. If you cancel one thing and start something else, you probably don't care if it's the same thread or a different one. (In fact it's probably better if you don't care. If you need precise control over which thread is doing what then something has gotten complicated.) You can't "abort" a thread and restart it anyway.
Regarding Thread.Abort:
The Thread.Abort method should be used with caution. Particularly when you call it to abort a thread other than the current thread, you do not know what code has executed or failed to execute when the ThreadAbortException is thrown, nor can you be certain of the state of your application or any application and user state that it is responsible for preserving. For example, calling Thread.Abort may prevent static constructors from executing or prevent the release of unmanaged resources.
It's like firing an employee by teleporting them out of the building without warning. What if they were in the middle of a phone call or carrying a stack of papers? That might be okay in an emergency, but it wouldn't be a normal way to operate. It would be better to let the employee know that they need to wrap up what they're doing immediately. Put down what you're carrying. Tell the customer that you can't finish entering their order and they'll need to call back.
You're describing an expected behavior, so it would be better to cancel the thread in an orderly way.
That's where we might use a CancellationToken. In effect you're passing an object to the thread and telling it to check it from time to time to see if it should cancel what it's doing.
So you could start your thread like this:
class Program
{
static void Main(string[] args)
{
using (var cts = new CancellationTokenSource())
{
ThreadPool.QueueUserWorkItem(DoSomethingOnAnotherThread, cts.Token);
// This is just for demonstration. It allows the other thread to run for a little while
// before it gets canceled.
Thread.Sleep(5000);
cts.Cancel();
}
}
private static void DoSomethingOnAnotherThread(object obj)
{
var cancellationToken = (CancellationToken) obj;
// This thread does its thing. Once in a while it does this:
if (cancellationToken.IsCancellationRequested)
{
return;
}
// Keep doing what it's doing.
}
}
Whatever the method is that's running in your separate thread, it's going to check IsCancellationRequested from time to time. If it's right in the middle of doing something it can stop. If it has unmanaged resources it can dispose them. But the important thing is that you can cancel what it does in a predictable way that leaves your application in a known state.
CancellationToken is one way to do this. In other really simple scenarios where the whole thing is happening inside one class you could also use a boolean field or property that acts as a flag to tell the thread if it needs to stop. The separate thread checks it to see if cancellation has been requested.
But using the CancellationToken makes it more manageable if you want to refactor and now the method executing on another thread is a in separate class. When you use a known pattern it makes it easier for the next person to understand what's going on.
Here's some documentation.
What about doing it this way:
private static Task t = null;
private static CancellationTokenSource cts = null;
static void Main(string[] args)
{
[get arg]
if (CanRedo(out var arg))
{
if (t != null)
{
cts.Cancel();
t.Wait();
}
// Set up a new task and matching cancellation token
cts = new CancellationTokenSource();
t = Task.Run(() => liveTask(arg, cts.Token));
}
}
private static void liveTask(object obj, CancellationToken ct)
{
string arg = obj.ToString();
while(!ct.IsCancellationRequested)
{
if (bot._isDone)
{
ExecuteInstruction(arg);
}
}
}
Tasks are cancellable, and I can see nothing in your thread that requires the same physical thread to be re-used.

How to return info from Callback method? C# 4.0

I am using WCF Async methods.
I face issue when I try to return the value of the callback function.
What are the possible methods of solution? (using .net 4.0, but not 4.5)
public static Object LoadInfo()
{
var service = new SomeWcfService();
service.BeginGetInfo(CallbackMethod, service);
// HOW TO GET INFROMATION FROM CALLBACK??
return INFORMATION;
}
private static void CallbackMethod(IAsyncResult ar)
{
// HOW TO PASS INFROMATION TO LoadInfo??
var INFORMATION = (ar.AsyncState as SomeWcfService).EndGetInfo(ar);
}
Note: All work should be asynchronously.
Thanks.
Better you design to use the async pattern than fight against it.
But, if you must access an async method synchronously, you can use a semaphore to block the calling thread until the async method returns.
public static Object LoadInfo()
{
// this is our semaphore
var blocker = new AutoResetEvent();
object result = null;
var service = new SomeWcfService();
// use a lambda instead of a method as the callback.
// this will result in a closure where we can access the result and blocker variables
service.BeginGetInfo(x =>
{
// We are on a different thread within this lambda
result = (x.AsyncState as SomeWcfService).EndGetInfo(ar);
// release anybody calling blocker.WaitOne
blocker.Set();
}, service);
// we are still on the original thread here, and
// BeginGetInfo has possibly not yet executed, so we must wait until Set is called
blocker.WaitOne(Timeout.Infinite);
return result;
}
This is rarely a good design choice. Aynchornous patterns are much better for responsive UI. Better to do something like this
public void LoadInfo()
{
// Makes the UI show a loading indicator, blocking all actions except for CANCEL
LoadingInfo = true;
var service = new SomeWcfService();
service.BeginGetInfo(CallbackMethod, service);
}
private void CallbackMethod(IAsyncResult ar)
{
// the UI is now released from loading
LoadingInfo = false;
// the UI is triggered to show our data
ViewModel.Data = (ar.AsyncState as SomeWcfService).EndGetInfo(ar);
}
Understanding async at first, especially with callbacks is tough. In your example you make an incorrect, but natural assumption...
public static Object LoadInfo()
{
var service = new SomeWcfService();
service.BeginGetInfo(CallbackMethod, service);
// HOW TO GET INFROMATION FROM CALLBACK??
// ERROR: You assume you have more work to do in this method,
// or that this is the place to return your results.
return INFORMATION;
}
The method you give below, is where the work occurs after your results are returned:
private static void CallbackMethod(IAsyncResult ar)
{
// HOW TO PASS INFROMATION TO LoadInfo??
// OOPS! No need to pass pack to LoadInfo - it's done...
var INFORMATION = (ar.AsyncState as SomeWcfService).EndGetInfo(ar);
}
Instead you will want something like this
public static void LoadInfo()
{
var service = new SomeWcfService();
// begin an asynchronous service call
// and handle the results in another method, "CallbackMethod"
service.BeginGetInfo(CallbackMethod, service);
// You can do other, non-service related,
// things here while the service call executes
}
Then your other method handles all the results:
private static void CallbackMethod(IAsyncResult ar)
{
var results = (ar.AsyncState as SomeWcfService).EndGetInfo(ar);
// Do whetever you need with results here
}
As Will pointed out in his excelent answer (+1, as if he needs it lol!), instead of having a separate call-back method, you can use an anonymous method with a lambda expression like:
public static void LoadInfo()
{
var service = new SomeWcfService();
// begin an asynchronous service call
// and handle the results in this anonymous method
service.BeginGetInfo(x =>
{
// B. This code block will be called when the service returns with results
var results = (ar.AsyncState as SomeWcfService).EndGetInfo(ar);
// Do whetever you need with results here
}, service);
// A. You can do other things here while the service call executes
// but debugging this gets more complicated because things will likely
// occur at A before they occur at B
}
So, the over-all mentality of Asynchronous is:
Your program sets up and begins a service call then keeps doing whatever else it wants, without waiting. Hint: This is a natural place to start a loading animation, and/or disable some controls.
When you made the async call, you gave, as one of your parameters, a method to run once the call is complete.
When the service returns with results, the method you specified is run to do work on the results. Hint: In this method, you can end the loading animation, and/or re-enable your controls, and plug the results into your ViewModel.

Is any part of this .net async api method not async

I using a API http://themoviedbapi.codeplex.com/ but if I call for example 7 instances of this method it takes 2-3 sek to run and in the meantime my app is locked. So is any part this method implemented wrongly so it aint run async?
#region GetMovieInfoAsyncMethods
private delegate void GetMovieInfoDelegate(int id, object userState, AsyncOperation asyncOp);
public void GetMovieInfoAsync(int id)
{
GetMovieInfoAsync(id, null);
}
public void GetMovieInfoAsync(int id, object userState)
{
AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(null);
GetMovieInfoDelegate worker = new GetMovieInfoDelegate(GetMovieInfoWorker);
worker.BeginInvoke(id, userState, asyncOp, null, null);
}
private void GetMovieInfoWorker(int id, object userState, AsyncOperation asyncOp)
{
Exception exception = null;
TmdbMovie movie = null;
try
{
movie = GetMovieInfo(id);
}
catch (Exception ex)
{
exception = ex;
}
ImdbMovieInfoCompletedEventArgs args = new ImdbMovieInfoCompletedEventArgs(movie, exception, false, userState);
asyncOp.PostOperationCompleted(
delegate(object e) { OnGetMovieInfoCompleted((ImdbMovieInfoCompletedEventArgs)e); },
args);
}
protected virtual void OnGetMovieInfoCompleted(ImdbMovieInfoCompletedEventArgs e)
{
if (GetMovieInfoCompleted != null)
GetMovieInfoCompleted(this, e);
}
#endregion
I think you should put some Debug.Write()-style tracing in there so you can see where things are starting and stopping.
My initial guess from your sourcecode posting is that when GetMovieInfoCompleted is fired, something that subscribes to it takes a long time to run (e.g. updating many UI components).
What you're doing in your code sample looks okay at first glance because you're calling Control.BeginInvoke() which wouldn't block. The whole point of BeginInvoke as opposed to Invoke is it's non-blocking.
UPDATE:
You had an interesting comment about BeginInvoke still blocking the UI thread. I wasn't aware of that because I don't use it. Instead, consider using one of the following:
The BackgroundWorker component.
ThreadPool.QueueUserWorkItem() (although that'll require more cross-thread marshalling on your part that BackgroundWorker would do for you).
If you're on .NET 4.0, look at the Parallel Task Library.

Using a named system semaphore as an event to trigger something in another process

I have a thread that runs all the time:
private void DoSomeStuffThread() {
Semaphore sem = new Semaphore(0, 3, "sem_DoStuff");
sem.WaitOne();
do {
//do some stuff
} while (sem.WaitOne());
}
I want to be able to only execute the stuff in the do block when something from another process says so. I am trying to use the "sem_DoStuff" named system semaphore to allow this to happen.
The code that gets executed in my other process:
public string DoStuff() {
try {
Semaphore sem = Semaphore.OpenExisting("sem_DoStuff");
sem.Release();
} catch (Exception e) {
return e.Message;
}
}
So, the idea is that when DoStuff gets called, the semaphore gets released, and DoSomeStuffThread stops waiting, executes what is in the do block, and then waits for DoStuff again before it is getting called. But, when DoStuff gets called, I'm getting the exception 'No handle of the given name exists.'. What am I doing wrong?
Thanks.
It turns out the problem was that I needed to put Global\ in front of the Semaphore name.
It seems like you have the order wrong. The semaphore sem_DoStuff needs to exist before the thread is created (and quite possibly before the function DoStuff is called). The method/process that invokes those should probably be the one that creates the semaphore.

Categories

Resources