1 //
2 // Copyright (c) 2010-2018 Antmicro
3 // Copyright (c) 2011-2015 Realtime Embedded
4 //
5 // This file is licensed under the MIT License.
6 // Full license text is available in 'licenses/MIT.txt'.
7 //
8 using System;
9 using Xwt;
10 using System.Threading;
11 using System.Collections.Concurrent;
12 using Antmicro.Renode.Exceptions;
13 
14 namespace Antmicro.Renode.UI
15 {
16     public static class ApplicationExtensions
17     {
ApplicationExtensions()18         static ApplicationExtensions()
19         {
20             actionsToRunInUIThread = new BlockingCollection<Action>();
21             var t = new Thread(() =>
22             {
23                 while(true)
24                 {
25                     var a = actionsToRunInUIThread.Take();
26                     Application.Invoke(a);
27                 }
28             });
29             t.IsBackground = true;
30             t.Name = "ApplicationExtensions GUI invoker";
31             t.Start();
32         }
33 
InvokeInUIThread(Action action)34         public static void InvokeInUIThread(Action action)
35         {
36             CheckXwtStatus();
37             if(Thread.CurrentThread.ManagedThreadId == XwtProvider.UiThreadId)
38             {
39                 action();
40             }
41             else
42             {
43                 Application.Invoke(action);
44             }
45         }
46 
InvokeInUIThreadNonBlocking(Action action)47         public static void InvokeInUIThreadNonBlocking(Action action)
48         {
49             CheckXwtStatus();
50             if(Thread.CurrentThread.ManagedThreadId == XwtProvider.UiThreadId)
51             {
52                 actionsToRunInUIThread.Add(action);
53             }
54             else
55             {
56                 Application.Invoke(action);
57             }
58         }
59 
InvokeInUIThreadAndWait(Func<T> function)60         public static T InvokeInUIThreadAndWait<T>(Func<T> function)
61         {
62             CheckXwtStatus();
63             if(Thread.CurrentThread.ManagedThreadId == XwtProvider.UiThreadId)
64             {
65                 return function();
66             }
67 
68             T result = default(T);
69             var mre = new ManualResetEventSlim();
70 
71             Application.Invoke(() =>
72             {
73                 result = function();
74                 mre.Set();
75             });
76 
77             mre.Wait();
78             return result;
79         }
80 
InvokeInUIThreadAndWait(Action action)81         public static void InvokeInUIThreadAndWait(Action action)
82         {
83             CheckXwtStatus();
84             if(Thread.CurrentThread.ManagedThreadId == XwtProvider.UiThreadId)
85             {
86                 action();
87                 return;
88             }
89 
90             var mre = new ManualResetEventSlim();
91             Application.Invoke(() =>
92             {
93                 action();
94                 mre.Set();
95             });
96 
97             mre.Wait();
98         }
99 
CheckXwtStatus()100         private static void CheckXwtStatus()
101         {
102             if(XwtProvider.UiThreadId == -1)
103             {
104                 throw new RecoverableException("An action requiring GUI environment detected, but the XWT provider is not started.");
105             }
106         }
107 
108         private static BlockingCollection<Action> actionsToRunInUIThread;
109     }
110 }
111 
112