views:

2826

answers:

4

I'm writing Application A and DLL B, both in C#.NET. How do I do the following:

  1. A calls function in B
  2. Want B to use delegate/callback to update status in UI of A

This is not about BackgroundWorker...that part works fine in A. What I can't see is how to let B know what function to call in A.

+3  A: 

You have two options. The most common is to have an event in B and have your UI in A subscribe to that event. B then fires that event.

The second option is to pass in a delegate from A as a parameter to the method call in B. B can then Invoke that delegate.

Rob Prouse
I was going for the second option, but the syntax has me baffled.
You're missing a third option. You can create a delegate in A to shadow the B method, such that B never needs to know anything about it. Great for calling methods in third-party libraries asynchonously that wouldn't normally support it.
Joel Coehoorn
I ended up trying both the first and second options. The syntax for the second was cleaner in my case. Thanks!
A: 

Pass in the callback object in the call A make to B. Use an interface (or tightly bound libraries). Make sure the callback object is thread aware and thread safe.

Brody
+5  A: 

To expand on Rob Prouse's answer, you need to declare a delegate and then pass a matching method into it.

In B:

public delegate void CallbackDelegate(string status);

public void DoWork(string param, CallbackDelegate callback)
{
    callback("status");
}

In A:

public void MyCallback(string status)
{
    // Update your UI.
}

And when you call the method:

B.DoWork("my params", MyCallback);
Jeromy Irvine
Thank you! I had just worked this out, so it is nice to have your confirmation.
Ofcourse, if A and B are in different assemblies, you may have to stick the the delegate in its own assembly to avoid recursive dependency problems.
Soraz
If the delegate is declared in B, how would you get a circular dependency?
Jeromy Irvine
I did put the delegate definition in its own DLL/assembly, which worked nicely for me.
You forgot to instantiate the callback handler
Brock Woolf
Brock Woolf - Since about 2.0 you don't need to explicitly declare your Delegate. The compiler will infer it as exampled above so this code is just fine. This also works with events and the += operator.
Kleinux
A: 

If you control B, then Rob Prouse or Brody's answers will work fine.

But what if you can't change B at all? In that case, you can always wrap a method in a delegate of your own making, as long it's signature matches that of the signature of the target method.

So, say you have a class instance named B with a public method named b() (from the B dll assembly, of course). Class A in the A application can call it asynchronously like this:

public class A
{
    delegate void BDelegate();

    public void BegineBMethod()
    {
        BDelegate b_method = new BDelegate(B.b);
        b_method.BeginInvoke(BCallback, null);
    }

    void BCallback(IAsyncResult ar)
    {
       // cleanup/get return value/check exceptions here
    }
}
Joel Coehoorn