5

To be clearer, I am referencing a factory method that did not used to be async. In a recent API upgrade, they made the old method obsolete and created a new async method. Now, our code base is originally from VS2010 when async did not yet exist. I would like to change the method call to the new version so that we don't throw deprecation warnings.

Now onto the problem: Any call to an async method seems to require an "await" in order to guarantee that the method actually completed and that any state data initialized in that method is available for subsequent operations. However, putting an "await" in the call requires that the calling method also be async, which then requires that the caller of that method also use an await, and so forth all the way up to the top of the call stack. The only way I've found to avoid this is to put the call to the async factory method in a void async method. However, Microsoft has specifically stated that that functionality only exists for event handlers and should be avoided otherwise.

Now, it's true that I could adjust every single function in the call stack. But that's not only irritating to deal with, but is also an extreme encapsulation violation. Why should a top-level class have to be changing its method headers just because some call to a function 27 layers down had to deal with an external API change? I suspect that I'm missing something very obvious, but from what it looks like, I have two options: Either change all the method headers or submit to a "bad programming practice." Is there another way? Thanks in advance for any input.

C. Williamson
  • 319
  • 3
  • 13
  • This is how async works. You could use `Task` directly, but it won't help you. – SLaks Jul 19 '16 at 22:39
  • 1
    To put it differently, async is far more than an implementation detail; it's a different way to _invoke_ the operation (or rather, to get a response). – SLaks Jul 19 '16 at 22:39
  • you're not alone. https://cdn.meme.am/instances/35796044.jpg – Dbl Jul 19 '16 at 22:43

1 Answers1

2

Is there another way?

Not really. Either the function call is synchronous (by definition, blocking the thread), or a function call is asynchronous (by definition, not blocking the thread). It's not possible to have a thread blocked and not blocked at the same time.

I recommend you upgrade your code to use async. This is the best long-term solution. Or, you could turn the obsolete warning off, or stay with an older version of your library.

That said, I did write an article on brownfield async development, which illustrates a variety of partially-async approaches and the drawbacks to each (spoiler: there is no perfect solution).

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • I understand what you're saying. I just wish there was a way to tell .NET, "Yeah, I know it's async, but for this call pretend it isn't." It's probably not a bad idea anyway to just go ahead and start making the entire program async, as you say. – C. Williamson Jul 19 '16 at 22:53