make C# method wait for JS event to happen

≯℡__Kan透↙ 提交于 2019-12-12 05:19:51

问题


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:

  1. save (a weakref to) the C# object in the dictionary under a unique key
  2. using Reflection create methods that take the unique key as an argument and allow reading fields and calling methods of the object
  3. expose these methods to JavaScript using RegisterJsObject
  4. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!