1

My object in C# will call some JavaScript when constructed through the webbrowser control. The JavaScript will then call back to our c# code with a success or failure. I need to have the constructor of the C# object wait until the JavaScript returns the callback before it leaves the constructor. How would I go about doing this?

Essentially, I need to make sure that the object will always be properly initialized when created. This is dependent on the javascript calling back, which is at least slightly variable.

Tim
  • 1,334
  • 2
  • 15
  • 29
  • 1
    related: http://stackoverflow.com/questions/8145479/can-constructors-be-async – Servy Sep 18 '13 at 18:47
  • possible duplicate of [The modifier async is not valid for this item](http://stackoverflow.com/questions/10997174/the-modifier-async-is-not-valid-for-this-item) – Servy Sep 18 '13 at 18:48

2 Answers2

0

While you cannot use async/await in a constructor, it still may be possible to make async JavaScript call-outs and wait for their completion, depending on what you actually do in JavaScript and inside the callback from JavaScript to C# . It's done by organizing a nested message loop, here's an example taking this approach. Note, this may be dangerous as it may lead to code reentrancy.

That said, you still might be able to refactor your code to use async/await with one of the approaches described by Stephen Cleary in his blog entry.

Community
  • 1
  • 1
noseratio
  • 59,932
  • 34
  • 208
  • 486
-1

Instead of having an async constructor (which is not possible with .NET, anyway (thanks Servy) (and I don't think any other framework that allows for that is a sane framework, if such a thing exists)), you should:

  • Construct your object in such a way that you don't depend on that Javascript call;
  • Call whatever logic you need that will be done past .NET boundaries, and when the Javascript is done and responds...
  • ... Call some initialize() method (name it like that or something similar).

You could have a flag in each instance telling whether is has already passed through the post-Javascript initialization, and some logic in your class so that its instances can only be considered to be in a valid, ready, usable state after that initialization step. Good luck and happy coding :)

Community
  • 1
  • 1
Geeky Guy
  • 9,229
  • 4
  • 42
  • 62
  • It's way easier and safer to just rely on a factory method to create such objects, and ensure that callers can *only* construct an instance through such a method, rather than doing this. This is described in the proposed duplicates as well. – Servy Sep 18 '13 at 18:57
  • So even if I had a factory, how would I ensure that the javascript has been properly been initialized? Given the variable nature of this action, the factory would either return null in the event of a non-properly initialized object, or the correct object in the event of a properly initialized one. I need to ensure that every time this object is requested, it will properly initialized (meaning the javascript will callback with a success). – Tim Sep 18 '13 at 19:22
  • You'd just have to do what I suggested inside the factory anyway. I think the factory pattern is tangential to the problem and solution here. – Geeky Guy Sep 18 '13 at 19:53
  • @Tim The factory would return a `Task`. If the creation operation failed you could either have it mark the task as faulted, or you could have it continue to retry until it succeeded (or fault after a set number of attempts). – Servy Sep 18 '13 at 19:54
  • @Renan It's not, because By adding a facade you prevent consumers of the object from being given an object that isn't fully initialized, and yours relies on consumers using it properly to avoid problems. With a factory method you ensure that they are not given the object until it is properly initialized. That is a key difference. – Servy Sep 18 '13 at 19:55
  • @Servy from a consumer's point of view, yes, you are right. But my focus here is getting the object built and initialized. Inside your factory logic you have to do something other than using a factory, and there you are constrained by not being able to use an async constructor again. I agree that having a factory separating this object creation from consumers is a good practice, but in a really low level this is not the real solution to the OP's problem. It is something that makes the solution better, though. – Geeky Guy Sep 18 '13 at 19:59
  • @Renan At the end of the day you took the solution from the proposed duplicate, made it a bit worse, and posted it as an answer. That important information about how such a factory method would be implemented is all still in the linked questions. – Servy Sep 18 '13 at 20:02