-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Expand file tree
/
Copy pathMethodRunnerQueue.cs
More file actions
116 lines (102 loc) · 4.88 KB
/
Copy pathMethodRunnerQueue.cs
File metadata and controls
116 lines (102 loc) · 4.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright © 2015 The CefSharp Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
using System;
using System.Threading;
using System.Threading.Tasks;
using CefSharp.Internals.Tasks;
namespace CefSharp.Internals
{
/// <summary>
/// MethodRunnerQueue - Async Javascript Binding methods are run
/// on the ThreadPool sequentially
/// </summary>
public sealed class MethodRunnerQueue : IMethodRunnerQueue
{
//Limit to 1 task per methodRunnerQueue
//https://social.msdn.microsoft.com/Forums/vstudio/en-US/d0bcb415-fb1e-42e4-90f8-c43a088537fb/aborting-a-long-running-task-in-tpl?forum=parallelextensions
private readonly LimitedConcurrencyLevelTaskScheduler taskScheduler = new LimitedConcurrencyLevelTaskScheduler(1);
private readonly IJavascriptObjectRepositoryInternal repository;
private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
/// <inheritdoc/>
public event EventHandler<MethodInvocationCompleteArgs> MethodInvocationComplete;
/// <summary>
/// Default constructor
/// </summary>
/// <param name="repository">javascript object repository</param>
public MethodRunnerQueue(IJavascriptObjectRepositoryInternal repository)
{
this.repository = repository;
}
/// <inheritdoc/>
public void Dispose()
{
//Cancel all tasks associated with this MethoRunnerQueue
cancellationTokenSource.Cancel();
}
/// <inheritdoc/>
public void Enqueue(MethodInvocation methodInvocation)
{
if(cancellationTokenSource.IsCancellationRequested)
{
return;
}
Task.Factory.StartNew(() =>
{
if (cancellationTokenSource.IsCancellationRequested)
{
return;
}
var result = ExecuteMethodInvocation(methodInvocation);
var handler = MethodInvocationComplete;
if (!cancellationTokenSource.Token.IsCancellationRequested && handler != null)
{
handler(this, new MethodInvocationCompleteArgs(result));
}
}, cancellationTokenSource.Token, TaskCreationOptions.HideScheduler, taskScheduler);
}
private MethodInvocationResult ExecuteMethodInvocation(MethodInvocation methodInvocation)
{
object returnValue = null;
string exception;
var success = false;
var nameConverter = repository.NameConverter;
//make sure we don't throw exceptions in the executor task
try
{
var result = repository.TryCallMethod(methodInvocation.ObjectId, methodInvocation.MethodName, methodInvocation.Parameters.ToArray());
success = result.Success;
returnValue = result.ReturnValue;
exception = result.Exception;
//We don't support Tasks by default
if (success && returnValue != null && (typeof(Task).IsAssignableFrom(returnValue.GetType())))
{
//Use StringBuilder to improve the formatting/readability of the error message
//I'm sure there's a better way I just cannot remember of the top of my head so going
//with this for now, as it's only for error scenaiors I'm not concerned about performance.
var builder = new System.Text.StringBuilder();
builder.AppendLine("Your method returned a Task which is not supported by default you must set CefSharpSettings.ConcurrentTaskExecution = true; before creating your first ChromiumWebBrowser instance.");
builder.AppendLine("This will likely change to the default at some point in the near future, subscribe to the issue link below to be notified of any changes.");
builder.AppendLine("See https://github.com/cefsharp/CefSharp/issues/2758 for more details, please report any issues you have there, make sure you have an example ready that reproduces your problem.");
success = false;
result = null;
exception = builder.ToString();
}
}
catch (Exception e)
{
exception = e.Message;
}
return new MethodInvocationResult
{
BrowserId = methodInvocation.BrowserId,
CallbackId = methodInvocation.CallbackId,
FrameId = methodInvocation.FrameId,
Message = exception,
Result = returnValue,
Success = success,
NameConverter = nameConverter
};
}
}
}