1

Two questions:

  1. How do I pass arguments to the AsyncCallback method?

  2. How do I invoke the AsyncCallback method?

Here's the background:

I am working on an old project in .NET Framework 3.5. I want to create an async method doing some works without blocking current thread. Since the project is an old version Async Await key words are not available, I plan to do all parallel works including some database queries and api calling in AsyncCallback method. I know AsyncState can be used to convey arguments. Because I need multiple arguments, I plan to include these arguments into an object and set the object to AsyncState, so I can cast AsyncState as the object to be used in AsyncCallback method. I didn't find a good way. I've found this link, but I don't use HttpWebRequest.

 public Class ArgumentObject
 {
      public string A{get;set;}
      public string B{get;set;}
      ...
 }
 public void CallBack(IAsyncResult result, ArgumentObject arObj)
 {
      Console.WriteLn(arObj.A);
      Console.WriteLn(arObj.B);
 }

The following are the code which call the AsyncCallBack method.

 var argumentsObj=new ArgumentObject{ A="argument1", B="argument2"..};

 AsyncCallback callback = (IAsyncResult result) => CallBack(result, argumentsObj);
 // How do I know it is triggered? I set the break point into CallBack method, but it never goes to there.

Any idea or correction is appreciated.

Community
  • 1
  • 1
Steven Zack
  • 4,984
  • 19
  • 57
  • 88

2 Answers2

1

Update: I finally found a way to pass arguments. I use a delegate and call BeginInvoke method.

static int DoSomething(string s, int t)
    {
        Console.WriteLine(s+t.ToString());
        return 0;
    }// this is the delegate method, you can define it anyway.

public delegate int MyDelegate(string s, int t);
MyDelegate x = new MyDelegate(DoSomething);
AsyncCallback callback = new AsyncCallback(CallBack);
var argumentsObj=new ArgumentObject{ A="argument1", B="argument2"..};
IAsyncResult ar = x.BeginInvoke("hello", 12, callback, argumentsObj);
// in my case, the first two parameters are not important, only the last two are important.

Now in Callback method I can cast the AsyncState into argument object:

var obj = (CallBackObj)result.AsyncState;

In CallBack method, don't forget to call EndInvoke method in order to guarantee not to leak memory or handles

MyDelegate x = (MyDelegate)((AsyncResult)result).AsyncDelegate;
        x.EndInvoke(result);
Steven Zack
  • 4,984
  • 19
  • 57
  • 88
  • Sorry, did not get this: `var obj = (CallBackObj)result.AsyncState;`... Anyway, in my case, when using this pattern for `DuplexChannelFactory` functionality, i'm getting invalid cast, because IAsyncState is of `System.ServiceModel.Dispatcher.MessageRpc` type. Don't know why and what to do with that. No info in internet. – Alexander Oct 30 '16 at 22:12
0

Not sure if this solution would be relevant in your case, but in my case I needed a common utility async task to check back with the caller that an ITaskHandler was still valid after it had switched over to the UI thread.

Now if I was in C++ I could simply pass a reference pointer to the object as an argument, but in C# things can get messy, so the simplest solution for me was create a single method interface for all the classes requiring the utility function.

public interface ITaskHandlerClient
{
    ITaskHandler GetTaskHandler();
}

and then pass the caller as an ITaskHandlerClient object.

public static async Task<bool> TaskHandlerProgressAsync(ITaskHandlerClient client,
    string text, int progress) { ... }
Greg C
  • 11
  • 2