I have some solution and question. I rummaged through the entire Internet, survived a sleepless week (well, almost :), but still I found a solution. Actually, here it is:

Create a stream that will be fully in power with WebCore Awesomium (and this will be the problem later):

Thread awesomiumThread = new Thread(new ThreadStart(() => { WebCore.Started += (s, crStr) => { awesomiumContext = SynchronizationContext.Current; }; WebCore.Run(); })); awesomiumThread.Start(); WebCore.Initialize(WebConfig.Default); 

SynchronizationContext awesomiumContext we have here is an amazing thing, bordering on magic (for me, at least :). Creates a context of the stream, with which you can then break into it at any time (look in more detail on the Internet).

And WebCore.Run() reserves (blocks) the thread in which it was launched, up to the call to WebCore.Shutdown() .

After this procedure, you can now call any method in the Awesomium stream with a command like this: awesomiumContext.Post(Method, Params); or awesomiumContext.Send(Method, Params) .

Now the biggest snag is actually my current problem. In the WebCore stream, there is no automatic update (in the usual sense), but it is possible to use events like DocumentReady or LoadingFrameComplete . But there is a big but. Wait for the update in the stream will not work, because any work in it blocks this thread and wait until the event triggers. So I had to scatter a rather big code into small pieces, throwing the poor browser from the main thread to the handler, then to another thread and back around, trying to catch the event handler's response. So I will be incredibly grateful if someone has a working way to wait for the page to load into Awesomium without ping-pong by WebViewer.

  • WebCore.Update() , by the way, can be called manually. - Regent
  • This was my first solution, but multithreading does not work with this approach, the application just crashes, without Exception, as decimated. - Andrei Tsapenko

1 answer 1

Use asynchronous programming and the TaskCompletionSource class. I don’t know the Awesomium event system, so I’ll write a solution in a general way; just fill in the exact event names.

 public Task<EventArgs> WaitForSomeEvent(CancellationToken token) { var tcs = new TaskCompletionSource<EventArgs>(); var registration = token.Register(() => ctx.TrySetCanceled()); EventHandler handler = e => ctx.TrySetResult(e); someObject.SomeEvent += handler; tcs.Task.ContinuewWith(_ => { someObject.SomeEvent -= handler; registration.Dispose(); }, TaskContinuationOptions.ExecuteSynchronously); return tcs.Task; } 

What's going on here? We create a TaskCompletionSource , hang up three event handlers and exit, returning the task to wait for the calling code. Further events can develop in one of two scenarios.

Scenario one - someObject.SomeEvent is triggered. Then we translate TaskCompletionSource to the "completed" state, passing the event parameter as the result of the work.

Scenario two - the wait was canceled. Then we cancel the TaskCompletionSource .

Regardless of the scenario, then the third handler is triggered, which I hung on the returned task itself - it cleans up the resources by removing the first two handlers (the third one does not need to be removed - it is one-time).

How to use this joy? Very simple:

 public async void Foo() { ... // делаем что-нибудь нужное await WaitForSomeEvent(CancellationToken.None); // Для простоты я никогда не отменяю ожидание ... // делаем что-нибудь еще } 

What happens in this code? First, the code block will be executed before the await operator. Then the WaitForSomeEvent method will subscribe to the SomeEvent event and return the task. Next, the await operator will see that the task has not yet been completed, will remember the current execution context, subscribe to the task - and return control from the method (yes, control from the asynchronous methods is returned on the first await operator).

After the task goes to any of the "completed" states (in this case, it can only go to the "completed" state - since we never cancel it), the await statement handler will retrieve the saved synchronization context and schedule it to continue running the method.

Thus, asynchronous programming, although it will not remove jumps over threads in runtime, will definitely help to clean up your code by gluing small pieces back into the asynchronous method.

  • I’m not testing it today, but I’ll see it tomorrow. Oh, how much I still have to learn: D - Andrei Tsapenko
  • Can I have a little more detail? Just awesomium is designed so that the thread in which it runs will never stop itself (except in the event of a crash), hence await WaitForSomeEvent (CancellationToken.None); just hang. - iRumba
  • @iRumba where did you get that await WaitForSomeEvent(CancellationToken.None); somehow connected with the life of the stream? - Pavel Mayorov
  • No reason, just suggested. Now I'm sharpening it for my task, I'll check it there - iRumba