-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for calling async methods on host objects (.NET, WinRT) #75
Comments
Our current AddRemoteObject method uses COM / IDispatch which doesn't really have an async notion. For .NET / WinRT we'll support async methods as promises in JS. |
Cross posting from #532 Some more context in case it helps: Alternatively, I could use |
It won't be available in the 1.0 release. Looking at our backlog and it's relative priority, I would guess Q2 2021 is when it might land. :( Instead of a return value, you could have the value returned asynchronously using a callback - there's an example of this in our sample app. This would make the JS look like:
I'm not exactly sure what this would look like in .NET though, so might require some experimentation. |
Ok thanks that's a much better alternative. I spent some time on it and was able to get it working in C#. It required an
Then implement a HostObject method to take a callback argument: public void TestAsyncViaCallback(string something, object callback)
{
string message = $"***TestAsyncViaCallback({something}) Called***";
Debug.Print(message);
// Simulate an async call to a remote machine
Task.Run(() =>
{
string result = "Asynchronous test via callback succeeded";
bool success = true;
InvokeMemberHelper.InvokeDispMethod(callback, null, success, result);
});
} And the JS code to call and process the return value: async function SendTestMessageAsyncViaCallback() {
try {
let message = document.getElementById("input-TestMessage").value;
let external = await window.chrome.webview.hostObjects.external;
await external.TestAsyncViaCallback(message, (success, res) => {
let output = `Succeeded: ${success}\nResult: ${res}`;
document.getElementById("result-TestMessage").value = output;
});
} catch (e) {
document.getElementById("result-TestMessage").value = `Error: ${e.toString()}`;
}
} Note the JS function takes a |
Glad you got it working! I'll keep you updated on when we have a fix for .NET async functions in general. Thanks! |
Just to be clear You can also return values back to JavaScript if you use the sync object. Which means pretty much if you need to return values from .NET into JavaScript sync is the only option. The problem is that you can't return a value when you use the This seems like a pretty big problem especially given that calling into the JavaScript the other way requires async code. So any method in .NET that is called from JavaScript and returns a value, and also needs to access the DOM from the .NET code, can't do it without a pretty good chance of deadlocking. I've gotten stopped out by this quite a bit. Just had a long Twitter thread on this and literally the answer (from David Fowler) was: "You're screwed. Wrap in Task.Run() and hope for the best". |
Hey @RickStrahl - I just gave this a try in our sample app and a separate .NET app with a host object that returns a value (bool in my test). When I call |
Ok... I'll take a look. A bit hard now as I've worked around the async issue in a different way. To be honest it's been a couple of updates back since I last tested as I needed a workaround at the time. In that case the result was a pending promise that never resolved. I gave up on this at the time because you mentioned that this was a known issue and not likely to get fixed at the time. I'd like to be pleasantly surprise though :-) |
@champnic |
@dimmelsw Yes, we are starting work on this very soon :) |
@champnic |
My guess would be early 2022, but maybe sooner if it's less complex than we think. |
I didn't realize this wasn't supported. I had just converted my WebView1 project to be more async methods required for it to be out-of-process. Going to make porting to WebView2 harder. |
@champnic |
@dimmelsw This work has just been checked in last week :) It should be available in the next prerelease SDK in about a week or two. Thanks! |
Thanks for working 👍 |
(I am the one who posted the original thread.)
Today, I released https://github.com/kekyo/DupeNukem If you are waiting for the interoperability code and are interested, give it a try. |
Hey all - just wanted to confirm that this support is now available in the 1.0.1189-prerelease SDK, using any runtime version 100.0.1183.0+. Thanks! |
How do I install it, runtime version 100.0.1183.0+ |
You'll need to use Microsoft Edge Canary/Dev/Beta: Let me know if that doesn't answer your question. Thanks! |
@champnic I seem to be getting an
I've been also trying to use the WebView2 JavaScript Debugger in VS, but it doesn't like me setting a break point in html, so it's hard to catch on load. Going to move my code to a button to see if I can try the Dev Tools debugger and inspect the native object. Here's my test project: |
@michael-hawker I was able to repro using your test app. Could you move this to a new issue and I'll get it opened as a bug. Thanks! |
@champnic I have tested @michael-hawker example using 1189-prerelease with various webview runtimes (Beta / Dev and Canary). None of these resolve the original issue. While I do not get the |
@rsegner We've had to revert the code for now as it was causing regressions when the SDK + runtime pairing was off. We'll be fixing the root cause and then checking the code back in, and will use @michael-hawker's sample app to help validate. Thanks! |
Cool, note originally, I had the order as: document.getElementById("prop1").innerHTML = await anobject.SomePropertyString;
document.getElementById("prop2").innerHTML = await anobject.SomeInteger;
document.getElementById("prop3").innerHTML = await anobject.MyEnumProp;
var result = await anobject.MyLongFunction();
console.log(result);
document.getElementById("wait").innerHTML = result;
document.getElementById("func1").innerHTML = await anobject.MyFirstFunction("true");
document.getElementById("func2").innerHTML = await anobject.MyFirstFunction("boo");
document.getElementById("func3").innerHTML = await anobject.MySecondFunction(7); As I'd expect there to be a delay in seeing the results for Just wanted to call this out for a more well-rounded test. 🙂 I think to clarify too, based on my understanding of the docs, even the properties and the synchronous function calls need to have Good to know it should be handy for validation though! 🎉 |
Realize the issue has not been marked as fixed, however, just tried @michael-hawker s app with WebView SDK v1.0.1222-prerelease and Edge runtime Canary (at the time of writing v102.0.1236.0). No longer getting an AccessViolation error, however also not getting the expected result of "Done!" from the async operation. |
@rsegner That's expected. Unfortunately we had to rollback the change for async host object functions because it was causing the access violation errors. |
@champnic Any news on this one? I am very keen on using this for a new development for my company. Happy to be an early adopter and provide any feedback. |
We are working on relanding the change. It's currently in a Pull Request and will hopefully be checked in soon! |
Hey all - we've fixed and relanded this change. It should be available in the next SDK pre-release package. Thanks! |
What is current status? |
This is available in 1.0.1305-prerelease. Please give it a try and let us know if it's working for you. Thanks! |
I tested this and it's working with Beta channel (104) and 1.0.1305-prerelease. It wasn't working with stable (103) yet. |
@champnic I'd also like to verify that it's safe to run a nested message loop (e.g. by showing a dialog) prior to the final result being returned asynchronously to JS. https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/threading-model#reentrancy talks about it not being safe to show dialogs inside the event handler, however ideally this would be safe as long as it wasn't done synchronously. For example, is this safe?
I could it see it being safe or unsafe depending on how the webview code is waiting for the result, e.g. if webview is waiting in a nested message loop for the async result then I could see this being dicey. Ideally that wouldn't be happening. |
Did you find out if this is safe to do? |
@david-risney I experienced constructing full-duplex asynchronous interoperable functions between javascript's Promise based and .NET's Task based helper function sets on only WebView1 window.notify() infrastructure.
Interface C# side:
Interface JavaScript side:
Improved our project implementation stability with asynchronous architecture on both Task and Promise (and can use async/await on both worlds) and shareable how apply asynchronous on our team technical discussion. I received feedback with very good.
Unfortunaterly I can't share it, these implementations are closed source, I strongly recommend more powerful interop ability on WebView2 when there're supported :)
AB#26646526
The text was updated successfully, but these errors were encountered: