diff --git a/samples/PortSD4AddInToSD5/WorkbenchSingletonIssueProvider.cs b/samples/PortSD4AddInToSD5/WorkbenchSingletonIssueProvider.cs
index b1b7fcdd6e..da25ff38e5 100644
--- a/samples/PortSD4AddInToSD5/WorkbenchSingletonIssueProvider.cs
+++ b/samples/PortSD4AddInToSD5/WorkbenchSingletonIssueProvider.cs
@@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
+using ICSharpCode.NRefactory.PatternMatching;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.SharpDevelop;
@@ -102,8 +103,7 @@ namespace PortSD4AddInToSD5
script => {
script.Replace(invocationExpression,
new IdentifierExpression("SD").Member("MainThread")
- .Invoke("InvokeAsync", arg)
- .Invoke("FireAndForget"));
+ .Invoke("InvokeAsyncAndForget", arg));
});
break;
}
@@ -122,6 +122,22 @@ namespace PortSD4AddInToSD5
});
break;
}
+ case "ICSharpCode.SharpDevelop.IMessageLoop.InvokeAsync":
+ // We used to recommend SD.MainThread.InvokeAsync(...).FireAndForget(),
+ // but it's better to use SD.MainThread.InvokeAsyncAndForget(...)
+ if (invocationExpression.Clone().Invoke("FireAndForget").IsMatch(invocationExpression.Parent.Parent)) {
+ var ident = invocationExpression.Parent.GetChildByRole(Roles.Identifier);
+ yield return new CodeIssue(
+ "Use InvokeAsyncAndForget() instead",
+ ident.StartLocation, ident.EndLocation,
+ new CodeAction("Use InvokeAsyncAndForget() instead",
+ script => {
+ var newInvocation = (InvocationExpression)invocationExpression.Clone();
+ ((MemberReferenceExpression)newInvocation.Target).MemberName = "InvokeAsyncAndForget";
+ script.Replace(invocationExpression.Parent.Parent, newInvocation);
+ }));
+ }
+ break;
}
}
}
diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SearchForIssuesCommand.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SearchForIssuesCommand.cs
index 7f80ea6cac..6f97078e09 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SearchForIssuesCommand.cs
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SearchForIssuesCommand.cs
@@ -124,6 +124,8 @@ namespace CSharpBinding.Refactoring
if (resultForFile != null) {
callback(resultForFile);
}
+ } catch (IOException) {
+ // ignore IO exceptions (e.g. a file is missing)
} catch (OperationCanceledException) {
throw;
} catch (Exception ex) {
diff --git a/src/Main/Base/Project/Services/IMessageLoop.cs b/src/Main/Base/Project/Services/IMessageLoop.cs
index 168bc7184c..3b2305e719 100644
--- a/src/Main/Base/Project/Services/IMessageLoop.cs
+++ b/src/Main/Base/Project/Services/IMessageLoop.cs
@@ -18,7 +18,7 @@ namespace ICSharpCode.SharpDevelop
public interface IMessageLoop
{
///
- /// Gets the thread corresponding to this message loop.
+ /// Gets the thread that runs this message loop.
///
Thread Thread { get; }
@@ -77,9 +77,12 @@ namespace ICSharpCode.SharpDevelop
T InvokeIfRequired(Func callback, DispatcherPriority priority, CancellationToken cancellationToken);
///
- /// Invokes the specified callback.
+ /// Invokes the specified callback on the message loop.
///
/// Returns a task that is signalled when the execution of the callback is completed.
+ ///
+ /// If the callback method causes an exception; the exception gets stored in the task object.
+ ///
Task InvokeAsync(Action callback);
///
Task InvokeAsync(Action callback, DispatcherPriority priority);
@@ -93,6 +96,18 @@ namespace ICSharpCode.SharpDevelop
///
Task InvokeAsync(Func callback, DispatcherPriority priority, CancellationToken cancellationToken);
+ ///
+ /// Invokes the specified callback on the message loop.
+ ///
+ ///
+ /// This method does not wait for the callback complete execution.
+ /// If this method is used on the main thread; the message loop must be pumped before the callback gets to run.
+ /// If the callback causes an exception, it is left unhandled.
+ ///
+ void InvokeAsyncAndForget(Action callback);
+ ///
+ void InvokeAsyncAndForget(Action callback, DispatcherPriority priority);
+
///
/// Waits , then executed on the message loop thread.
///
diff --git a/src/Main/Base/Test/Utils/FakeMessageLoop.cs b/src/Main/Base/Test/Utils/FakeMessageLoop.cs
index 604bfb0315..50f9dc3e83 100644
--- a/src/Main/Base/Test/Utils/FakeMessageLoop.cs
+++ b/src/Main/Base/Test/Utils/FakeMessageLoop.cs
@@ -4,6 +4,7 @@
using System;
using System.Threading;
using System.Threading.Tasks;
+using System.Windows.Threading;
namespace ICSharpCode.SharpDevelop
{
@@ -19,7 +20,7 @@ namespace ICSharpCode.SharpDevelop
}
}
- public System.Windows.Threading.Dispatcher Dispatcher {
+ public Dispatcher Dispatcher {
get {
throw new NotImplementedException();
}
@@ -55,12 +56,12 @@ namespace ICSharpCode.SharpDevelop
callback();
}
- public void InvokeIfRequired(Action callback, System.Windows.Threading.DispatcherPriority priority)
+ public void InvokeIfRequired(Action callback, DispatcherPriority priority)
{
callback();
}
- public void InvokeIfRequired(Action callback, System.Windows.Threading.DispatcherPriority priority, CancellationToken cancellationToken)
+ public void InvokeIfRequired(Action callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
callback();
}
@@ -70,12 +71,12 @@ namespace ICSharpCode.SharpDevelop
return callback();
}
- public T InvokeIfRequired(Func callback, System.Windows.Threading.DispatcherPriority priority)
+ public T InvokeIfRequired(Func callback, DispatcherPriority priority)
{
return callback();
}
- public T InvokeIfRequired(Func callback, System.Windows.Threading.DispatcherPriority priority, CancellationToken cancellationToken)
+ public T InvokeIfRequired(Func callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
return callback();
}
@@ -85,12 +86,12 @@ namespace ICSharpCode.SharpDevelop
throw new NotImplementedException();
}
- public Task InvokeAsync(Action callback, System.Windows.Threading.DispatcherPriority priority)
+ public Task InvokeAsync(Action callback, DispatcherPriority priority)
{
throw new NotImplementedException();
}
- public Task InvokeAsync(Action callback, System.Windows.Threading.DispatcherPriority priority, CancellationToken cancellationToken)
+ public Task InvokeAsync(Action callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
@@ -100,12 +101,22 @@ namespace ICSharpCode.SharpDevelop
throw new NotImplementedException();
}
- public Task InvokeAsync(Func callback, System.Windows.Threading.DispatcherPriority priority)
+ public Task InvokeAsync(Func callback, DispatcherPriority priority)
{
throw new NotImplementedException();
}
- public Task InvokeAsync(Func callback, System.Windows.Threading.DispatcherPriority priority, CancellationToken cancellationToken)
+ public Task InvokeAsync(Func callback, DispatcherPriority priority, CancellationToken cancellationToken)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void InvokeAsyncAndForget(Action callback)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void InvokeAsyncAndForget(Action callback, DispatcherPriority priority)
{
throw new NotImplementedException();
}
diff --git a/src/Main/SharpDevelop/Parser/LoadSolutionProjects.cs b/src/Main/SharpDevelop/Parser/LoadSolutionProjects.cs
index 9b54ca9b93..c58dd808a6 100644
--- a/src/Main/SharpDevelop/Parser/LoadSolutionProjects.cs
+++ b/src/Main/SharpDevelop/Parser/LoadSolutionProjects.cs
@@ -40,11 +40,10 @@ namespace ICSharpCode.SharpDevelop.Parser
void RaiseThreadStarted()
{
threadRunningTime = Stopwatch.StartNew();
- SD.MainThread.InvokeAsync(
- delegate {
- IsRunning = true;
- Started(this, EventArgs.Empty);
- }).FireAndForget();
+ SD.MainThread.InvokeAsyncAndForget(delegate {
+ IsRunning = true;
+ Started(this, EventArgs.Empty);
+ });
}
void RaiseThreadEnded()
diff --git a/src/Main/SharpDevelop/Services/DispatcherMessageLoop.cs b/src/Main/SharpDevelop/Services/DispatcherMessageLoop.cs
index 288d0cd292..4073fdeed5 100644
--- a/src/Main/SharpDevelop/Services/DispatcherMessageLoop.cs
+++ b/src/Main/SharpDevelop/Services/DispatcherMessageLoop.cs
@@ -128,15 +128,25 @@ namespace ICSharpCode.SharpDevelop
return dispatcher.InvokeAsync(callback, priority, cancellationToken).Task;
}
+ public void InvokeAsyncAndForget(Action callback)
+ {
+ dispatcher.BeginInvoke(callback);
+ }
+
+ public void InvokeAsyncAndForget(Action callback, DispatcherPriority priority)
+ {
+ dispatcher.BeginInvoke(callback, priority);
+ }
+
public async void CallLater(TimeSpan delay, Action method)
{
await Task.Delay(delay).ConfigureAwait(false);
- InvokeAsync(method).FireAndForget();
+ InvokeAsyncAndForget(method);
}
IAsyncResult ISynchronizeInvoke.BeginInvoke(Delegate method, object[] args)
{
- return dispatcher.InvokeAsync