Skip to content

Commit 136c90e

Browse files
dellis1972jonpryor
authored andcommitted
[Xamarin.Android.Build.Tasks] Add LogCustomBuildEvent method to AsyncTask (#1065)
There is a possilility that we might be locking up the UI thread when logging CustomBuildEvents.. This happens in the `InstallPackageAssemblies` task. Currently we only use BuildEngine.LogCustomEvent Which may well cause problems when called from a non UI thread. So in keeping with the other Log methods available we should add a new LogCustomBuildEvent. This will queue and marshall the data to the UI Thread just like the other methods do.
1 parent 7acd0d5 commit 136c90e

File tree

1 file changed

+57
-58
lines changed

1 file changed

+57
-58
lines changed

src/Xamarin.Android.Build.Tasks/Tasks/AsyncTask.cs

Lines changed: 57 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ public class AsyncTask : Task, ICancelableTask {
1212
Queue logMessageQueue =new Queue ();
1313
Queue warningMessageQueue = new Queue ();
1414
Queue errorMessageQueue = new Queue ();
15+
Queue customMessageQueue = new Queue ();
1516
ManualResetEvent logDataAvailable = new ManualResetEvent (false);
1617
ManualResetEvent errorDataAvailable = new ManualResetEvent (false);
1718
ManualResetEvent warningDataAvailable = new ManualResetEvent (false);
19+
ManualResetEvent customDataAvailable = new ManualResetEvent (false);
1820
ManualResetEvent taskCancelled = new ManualResetEvent (false);
1921
ManualResetEvent completed = new ManualResetEvent (false);
2022
bool isRunning = true;
@@ -26,6 +28,7 @@ private enum WaitHandleIndex
2628
LogDataAvailable,
2729
ErrorDataAvailable,
2830
WarningDataAvailable,
31+
CustomDataAvailable,
2932
TaskCancelled,
3033
Completed,
3134
}
@@ -107,18 +110,13 @@ public void LogMessage (string message, MessageImportance importance = MessageIm
107110
#pragma warning restore 618
108111
}
109112

110-
lock (logMessageQueue.SyncRoot) {
111-
logMessageQueue.Enqueue (new BuildMessageEventArgs (
113+
var data = new BuildMessageEventArgs (
112114
message: message,
113-
helpKeyword : null,
115+
helpKeyword: null,
114116
senderName: null,
115117
importance: importance
116-
));
117-
lock (_eventlock) {
118-
if (isRunning)
119-
logDataAvailable.Set ();
120-
}
121-
}
118+
);
119+
EnqueueMessage (logMessageQueue, data, logDataAvailable);
122120
}
123121

124122
public void LogError (string message)
@@ -160,8 +158,7 @@ public void LogError (string code, string message, string file = null, int lineN
160158
#pragma warning restore 618
161159
}
162160

163-
lock (errorMessageQueue.SyncRoot) {
164-
errorMessageQueue.Enqueue (new BuildErrorEventArgs (
161+
var data = new BuildErrorEventArgs (
165162
subcategory: null,
166163
code: code,
167164
file: file,
@@ -172,12 +169,8 @@ public void LogError (string code, string message, string file = null, int lineN
172169
message: message,
173170
helpKeyword: null,
174171
senderName: null
175-
));
176-
lock (_eventlock) {
177-
if (isRunning)
178-
errorDataAvailable.Set ();
179-
}
180-
}
172+
);
173+
EnqueueMessage (errorMessageQueue, data, errorDataAvailable);
181174
}
182175

183176
public void LogWarning (string message, params object[] messageArgs)
@@ -193,9 +186,7 @@ public void LogWarning (string message)
193186
return;
194187
#pragma warning restore 618
195188
}
196-
197-
lock (warningMessageQueue.SyncRoot) {
198-
warningMessageQueue.Enqueue (new BuildWarningEventArgs (
189+
var data = new BuildWarningEventArgs (
199190
subcategory: null,
200191
code: null,
201192
file: null,
@@ -206,12 +197,19 @@ public void LogWarning (string message)
206197
message: message,
207198
helpKeyword: null,
208199
senderName: null
209-
));
210-
lock (_eventlock) {
211-
if (isRunning)
212-
warningDataAvailable.Set ();
213-
}
200+
);
201+
EnqueueMessage (warningMessageQueue, data, warningDataAvailable);
202+
}
203+
204+
public void LogCustomBuildEvent (CustomBuildEventArgs e)
205+
{
206+
if (UIThreadId == Thread.CurrentThread.ManagedThreadId) {
207+
#pragma warning disable 618
208+
BuildEngine.LogCustomEvent (e);
209+
return;
210+
#pragma warning restore 618
214211
}
212+
EnqueueMessage (customMessageQueue, e, customDataAvailable);
215213
}
216214

217215
public override bool Execute ()
@@ -222,42 +220,25 @@ public override bool Execute ()
222220
#pragma warning restore 618
223221
}
224222

225-
private void LogMessages ()
223+
private void EnqueueMessage (Queue queue, object item, ManualResetEvent resetEvent)
226224
{
227-
lock (logMessageQueue.SyncRoot) {
228-
while (logMessageQueue.Count > 0) {
229-
var args = (BuildMessageEventArgs)logMessageQueue.Dequeue ();
230-
#pragma warning disable 618
231-
Log.LogMessage (args.Importance, args.Message);
232-
#pragma warning restore 618
233-
}
234-
logDataAvailable.Reset ();
235-
}
236-
}
237-
238-
private void LogErrors ()
239-
{
240-
lock (errorMessageQueue.SyncRoot) {
241-
while (errorMessageQueue.Count > 0) {
242-
var args = (BuildErrorEventArgs)errorMessageQueue.Dequeue ();
243-
#pragma warning disable 618
244-
Log.LogCodedError (args.Code, file: args.File, lineNumber: args.LineNumber, message: args.Message);
245-
#pragma warning restore 618
225+
lock (queue.SyncRoot) {
226+
queue.Enqueue (item);
227+
lock (_eventlock) {
228+
if (isRunning)
229+
resetEvent.Set ();
246230
}
247-
errorDataAvailable.Reset ();
248231
}
249232
}
250233

251-
private void LogWarnings ()
234+
private void LogInternal<T> (Queue queue, Action<T> action, ManualResetEvent resetEvent)
252235
{
253-
lock (warningMessageQueue.SyncRoot) {
254-
while (warningMessageQueue.Count > 0) {
255-
var args = (BuildWarningEventArgs)warningMessageQueue.Dequeue ();
256-
#pragma warning disable 618
257-
Log.LogWarning (args.Message);
258-
#pragma warning restore 618
236+
lock (queue.SyncRoot) {
237+
while (queue.Count > 0) {
238+
var args = (T)queue.Dequeue ();
239+
action (args);
259240
}
260-
warningDataAvailable.Reset ();
241+
resetEvent.Reset ();
261242
}
262243
}
263244

@@ -267,6 +248,7 @@ protected void WaitForCompletion ()
267248
logDataAvailable,
268249
errorDataAvailable,
269250
warningDataAvailable,
251+
customDataAvailable,
270252
taskCancelled,
271253
completed,
272254
};
@@ -277,13 +259,30 @@ protected void WaitForCompletion ()
277259
var index = (WaitHandleIndex)System.Threading.WaitHandle.WaitAny (handles, TimeSpan.FromMilliseconds (10));
278260
switch (index) {
279261
case WaitHandleIndex.LogDataAvailable:
280-
LogMessages ();
262+
LogInternal<BuildMessageEventArgs> (logMessageQueue, (e) => {
263+
#pragma warning disable 618
264+
Log.LogMessage (e.Importance, e.Message);
265+
#pragma warning restore 618
266+
}, logDataAvailable);
281267
break;
282-
case WaitHandleIndex.ErrorDataAvailable:
283-
LogErrors ();
268+
case WaitHandleIndex.ErrorDataAvailable:
269+
LogInternal<BuildErrorEventArgs> (errorMessageQueue, (e) => {
270+
#pragma warning disable 618
271+
Log.LogCodedError (e.Code, file: e.File, lineNumber: e.LineNumber, message: e.Message);
272+
#pragma warning restore 618
273+
}, errorDataAvailable);
284274
break;
285275
case WaitHandleIndex.WarningDataAvailable:
286-
LogWarnings ();
276+
LogInternal<BuildWarningEventArgs> (warningMessageQueue, (e) => {
277+
#pragma warning disable 618
278+
Log.LogWarning (e.Message);
279+
#pragma warning restore 618
280+
}, warningDataAvailable);
281+
break;
282+
case WaitHandleIndex.CustomDataAvailable:
283+
LogInternal<CustomBuildEventArgs> (customMessageQueue, (e) => {
284+
BuildEngine.LogCustomEvent (e);
285+
}, customDataAvailable);
287286
break;
288287
case WaitHandleIndex.TaskCancelled:
289288
tcs.Cancel ();

0 commit comments

Comments
 (0)