Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Commit 7272152

Browse files
committed
Don't trample an existing SynchronizationContext
1 parent 8cd070a commit 7272152

File tree

2 files changed

+12
-101
lines changed

2 files changed

+12
-101
lines changed

src/GitHub.Api/Application/ApplicationManagerBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ public event Action<IProgress> OnProgress
2828

2929
public ApplicationManagerBase(SynchronizationContext synchronizationContext, IEnvironment environment)
3030
{
31+
UIScheduler = ThreadingHelper.GetUIScheduler(synchronizationContext);
32+
3133
SynchronizationContext = synchronizationContext;
32-
SynchronizationContext.SetSynchronizationContext(SynchronizationContext);
3334
ThreadingHelper.SetUIThread();
34-
UIScheduler = TaskScheduler.FromCurrentSynchronizationContext();
3535
ThreadingHelper.MainThreadScheduler = UIScheduler;
3636

3737
Environment = environment;
Lines changed: 10 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using System;
2-
using System.Runtime.CompilerServices;
3-
using System.Threading;
1+
using System.Threading;
42
using System.Threading.Tasks;
53

64
namespace GitHub.Unity
@@ -19,102 +17,15 @@ public static void SetUIThread()
1917

2018
public static bool InUIThread => InMainThread || Guard.InUnitTestRunner;
2119

22-
/// <summary>
23-
/// Switch to the UI thread
24-
/// Auto-disables switching when running in unit test mode
25-
/// </summary>
26-
/// <returns></returns>
27-
public static IAwaitable SwitchToMainThreadAsync()
20+
public static TaskScheduler GetUIScheduler(SynchronizationContext synchronizationContext)
2821
{
29-
return Guard.InUnitTestRunner ?
30-
new AwaitableWrapper() :
31-
new AwaitableWrapper(MainThreadScheduler);
22+
// quickly swap out the sync context so we can leverage FromCurrentSynchronizationContext for our ui scheduler
23+
var currentSyncContext = SynchronizationContext.Current;
24+
SynchronizationContext.SetSynchronizationContext(synchronizationContext);
25+
var ret = TaskScheduler.FromCurrentSynchronizationContext();
26+
if (currentSyncContext != null)
27+
SynchronizationContext.SetSynchronizationContext(currentSyncContext);
28+
return ret;
3229
}
33-
34-
35-
/// <summary>
36-
/// Switch to a thread pool background thread if the current thread isn't one, otherwise does nothing
37-
/// Auto-disables switching when running in unit test mode
38-
/// </summary>
39-
/// <param name="scheduler"></param>
40-
/// <returns></returns>
41-
public static IAwaitable SwitchToThreadAsync(TaskScheduler scheduler = null)
42-
{
43-
return Guard.InUnitTestRunner ?
44-
new AwaitableWrapper() :
45-
new AwaitableWrapper(scheduler ?? TaskManager.Instance.ConcurrentScheduler);
46-
}
47-
48-
class AwaitableWrapper : IAwaitable
49-
{
50-
Func<IAwaiter> getAwaiter;
51-
52-
public AwaitableWrapper()
53-
{
54-
getAwaiter = () => new AwaiterWrapper();
55-
}
56-
57-
public AwaitableWrapper(TaskScheduler scheduler)
58-
{
59-
getAwaiter = () => new AwaiterWrapper(new TaskSchedulerAwaiter(scheduler));
60-
}
61-
62-
public IAwaiter GetAwaiter() => getAwaiter();
63-
}
64-
65-
class AwaiterWrapper : IAwaiter
66-
{
67-
Func<bool> isCompleted;
68-
Action<Action> onCompleted;
69-
Action getResult;
70-
71-
public AwaiterWrapper()
72-
{
73-
isCompleted = () => true;
74-
onCompleted = c => c();
75-
getResult = () => { };
76-
}
77-
78-
public AwaiterWrapper(TaskSchedulerAwaiter awaiter)
79-
{
80-
isCompleted = () => awaiter.IsCompleted;
81-
onCompleted = c => awaiter.OnCompleted(c);
82-
getResult = () => awaiter.GetResult();
83-
}
84-
85-
public bool IsCompleted => isCompleted();
86-
87-
public void OnCompleted(Action continuation) => onCompleted(continuation);
88-
89-
public void GetResult() => getResult();
90-
}
91-
92-
public struct TaskSchedulerAwaiter : INotifyCompletion
93-
{
94-
private readonly TaskScheduler scheduler;
95-
96-
public bool IsCompleted
97-
{
98-
get
99-
{
100-
return (this.scheduler == TaskManager.Instance.UIScheduler && InUIThread) || (this.scheduler != TaskManager.Instance.UIScheduler && !InUIThread);
101-
}
102-
}
103-
104-
public TaskSchedulerAwaiter(TaskScheduler scheduler)
105-
{
106-
this.scheduler = scheduler;
107-
}
108-
109-
public void OnCompleted(Action action)
110-
{
111-
Task.Factory.StartNew(action, TaskManager.Instance.Token, TaskCreationOptions.None, this.scheduler);
112-
}
113-
114-
public void GetResult()
115-
{
116-
}
117-
}
118-
11930
}
120-
}
31+
}

0 commit comments

Comments
 (0)