问题
Intro
I'm programming a project where C# and JavaScript code need to work together, so I decided to use CefSharp as it guarantees the latest JS features (in contrast with WebView).
The Goal
Now I need to create an async C# method which would call an async JS function and then wait for it to finish. The problem is that JavaScript doesn't have anything like the await
keyword, so everything is defined in terms of events.
This is what the Javascript code looks like:
var name1 = "A";
var name2 = "B";
library.renameObject("A","B");
library.onrename = function(from, to){
if(from === "A"){
//let C# know
}
}
And the C# code should ideally be something like this:
class FooObject
{
string Name;
async Task Rename(string newName)
{
await mainFrame.EvaluateScriptAsync(@"
//The JS code
");
Name = newName;
}
}
The Problem
At first I thought using a task/promise would do the job, but after some testing I found out that it's impossible to pass objects between JS and C#.
This means that when I tried to pass TaskCompletionSource
to an IJavascriptCallback
, I got
System.NotSupportedException: Complex types cannot be serialized to Cef lists
Then I tried to return a Promise
from the JavaScript code, but in C# I always got null
.
A Bad Solution
I'm aware that using reflection, proxies and Dictionary<int, WeakRef<object>>
I could provide an interface, so that any C# object could be accessed from JavaScript in a way that would be indistinguishable from using an actual JS object. The approach would be:
- save (a weakref to) the C# object in the dictionary under a unique key
- using
Reflection
create methods that take the unique key as an argument and allow reading fields and calling methods of the object - expose these methods to JavaScript using
RegisterJsObject
- create a
Proxy
that would mimic an ordinary JS object and call the exposed C# methods in the background.
The bad news with this solution is that in JavaScript there are no destructors/finalizers, so I have no control over the V8 GC. This means the C# objects would stay there forever (memory leak) or get collected by the .Net GC too early (null pointer exception).
来源:https://stackoverflow.com/questions/44463255/make-c-sharp-method-wait-for-js-event-to-happen