19

I have a generated code with partial method

{
    ...
    partial void InterceptOperationCall(IOperationContext context);
    ...

    async Task SomeMethod()
    {
        InterceptOperationCall(cntx);
        await LongOperation(cntx);
    }
}

and handwrited partial

{
    partial void InterceptOperationCall(IOperationContext context)
    {
    }
}

I need to do async calls inside InterceptOperationCall Does any one knows some way to workaround partial method restrictions?

Another words: I want to do InterceptOperationCall asynchronously and guaranteed before long operation, at the same time i want to optionaly declare body of this method in another file.

UPD as workaround solution i chose to:

  • not use generated partial method stubs, and wrap with dynamic proxy (Castle.DynamicProxy) and intercept with AsyncInterceptorBase from (Nito.AsyncEx)
  • another option I see rewrite codegenerator

Any way I keep looking for better solution, and if someone know another ways to provide optional ability to wrap async calls with somoe async logic please help me.

gabba
  • 2,815
  • 2
  • 27
  • 48
  • If you want the restrictions of async partial method can find them in docs. But if you need to workaround partial method restrictions you need to provide more info. – Llazar Oct 22 '18 at 19:29
  • @Llazar, thanks for attention, I added some detail of my problem, can you tell what info you need? – gabba Oct 22 '18 at 20:56
  • 1
    @gabba is it that you want to be able to await the partial method or be able to invoke an awaitable function withing the partial method? The shown example is a `void` method so I am asking for clarification. – Nkosi Oct 25 '18 at 11:30
  • if rewriting the codegenerator is an option then I suggest rewriting it to be more compliant with async-await API. – Nkosi Oct 25 '18 at 17:08
  • @Nkosi, Could you provide a some sample or a give an Idea? – gabba Oct 26 '18 at 12:44

3 Answers3

1

You can use the async keyword when implementing the partial method.

So

async partial void InterceptOperationCall(IOperationContext context) {

}

should be no problem.

Peter Schneider
  • 2,879
  • 1
  • 14
  • 17
  • 4
    Can you safely suggest `async void` without knowing the context (no pun intended) of the code in question? – Kenneth K. Oct 22 '18 at 19:18
  • No... I thought the user didn't know how to wire up the async implementation for the auto generated method. Yet there are [gotchas](https://msdn.microsoft.com/en-us/magazine/jj991977.aspx) to take care about... – Peter Schneider Oct 22 '18 at 19:26
  • 1
    @PeterSchneider, great! it will compile and work, but order of execution of methods InterceptOperationCall, LongOperation depends on race condition. Did you know some way to make this construction awaitable? – gabba Oct 22 '18 at 20:50
  • 2
    @gabba sure, you return `async Task` instead of async void (and now you see the problem with partial classes and async methods). You may need to re-think your design to not use partial classes anymore. – Scott Chamberlain Oct 25 '18 at 08:44
  • @ScottChamberlain, I compelled to use partials because need to use existed code, could you explain your idea with async Task? – gabba Oct 25 '18 at 10:28
0

I don't see a way around this that doesn't suffer all the drawbacks of async void in general (as discussed in the linked Stephen Cleary article in Peter Schneider's comment)

I think your best bet if you cannot find or write a sync version of the async APIs in question is to call the async methods, then use task.Wait() to wait for completion. If you have multiple async calls, compose them with ContinueWith. Essentially you need to use the Task library in the .Net 4.0 style.

Jonas Høgh
  • 10,358
  • 1
  • 26
  • 46
-1

Partial methods are just like interfaces. They're a contract. Anyone implementing the partial method, just like an interface method, is fulfilling that contract. In this case, the contract of the method is a synchronous method. There's no way to have an asynchronous implementation, because a proper asynchronous implementation of that method requires the caller of the method to know that it's an asynchronous method, and to act accordingly. Since the caller has written the contract as being a synchronous method, that isn't happening.

So your solutions are to change the contract for the method to be asynchronous, meaning changing the partial method's declaration, or to provide a synchronous, rather than asynchronous, implementation.

I suppose a third option would be to have the interface (in this case, partial methods) support both. Have two partial methods, one asynchronous, one synchronous, and let the implementation provide whichever one they want.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • could you provide example of partial asynchronous method? Or point me to some example? – gabba Nov 02 '18 at 08:27
  • @gabba It would simply have the signature of any other asynchronous method. It would return a `Task`, or in an older style of coding, accept a callback, or use some other means of informing the caller that it has finished. But these days it would generally just be returning a `Task`. – Servy Nov 02 '18 at 13:20
  • 1
    as far as I know partial methods couldn't return value. Partial methods must be void. – gabba Nov 02 '18 at 14:04
  • @gabba Then it'd have to accept a callback, or some other form of asynchrony that can be passed as a parameter instead of returned by the method. – Servy Nov 02 '18 at 14:05