Better error handling for DispatcherHelper when not initialized
Added a way to reset the dispatcher in DispatcherHelper
This commit is contained in:
Родитель
30dc6dca24
Коммит
d2651f1aff
|
@ -15,6 +15,7 @@
|
|||
// ****************************************************************************
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
#if NETFX_CORE
|
||||
using Windows.UI.Core;
|
||||
|
@ -36,8 +37,8 @@ namespace GalaSoft.MvvmLight.Threading
|
|||
/// Helper class for dispatcher operations on the UI thread.
|
||||
/// </summary>
|
||||
//// [ClassInfo(typeof(DispatcherHelper),
|
||||
//// VersionString = "4.0.4",
|
||||
//// DateString = "201206191330",
|
||||
//// VersionString = "4.1.6",
|
||||
//// DateString = "201305190047",
|
||||
//// Description = "Helper class for dispatcher operations on the UI thread.",
|
||||
//// UrlContacts = "http://www.galasoft.ch/contact_en.html",
|
||||
//// Email = "laurent@galasoft.ch")]
|
||||
|
@ -70,6 +71,13 @@ namespace GalaSoft.MvvmLight.Threading
|
|||
/// thread.</param>
|
||||
public static void CheckBeginInvokeOnUI(Action action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CheckDispatcher();
|
||||
|
||||
#if NETFX_CORE
|
||||
if (UIDispatcher.HasThreadAccess)
|
||||
#else
|
||||
|
@ -88,6 +96,30 @@ namespace GalaSoft.MvvmLight.Threading
|
|||
}
|
||||
}
|
||||
|
||||
private static void CheckDispatcher()
|
||||
{
|
||||
if (UIDispatcher == null)
|
||||
{
|
||||
var error = new StringBuilder("The DispatcherHelper is not initialized.");
|
||||
error.AppendLine();
|
||||
|
||||
#if SILVERLIGHT
|
||||
#if WINDOWS_PHONE
|
||||
error.Append("Call DispatcherHelper.Initialize() at the end of App.InitializePhoneApplication.");
|
||||
#else
|
||||
error.Append("Call DispatcherHelper.Initialize() in Application_Startup (App.xaml.cs).");
|
||||
#endif
|
||||
#elif NETFX_CORE
|
||||
error.Append("Call DispatcherHelper.Initialize() at the end of App.OnLaunched.");
|
||||
#else
|
||||
error.Append("Call DispatcherHelper.Initialize() in the static App constructor.");
|
||||
#endif
|
||||
|
||||
throw new InvalidOperationException(error.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
#if NETFX_CORE
|
||||
/// <summary>
|
||||
/// Invokes an action asynchronously on the UI thread.
|
||||
/// </summary>
|
||||
|
@ -104,6 +136,8 @@ namespace GalaSoft.MvvmLight.Threading
|
|||
public static DispatcherOperation RunAsync(Action action)
|
||||
#endif
|
||||
{
|
||||
CheckDispatcher();
|
||||
|
||||
#if NETFX_CORE
|
||||
return UIDispatcher.RunAsync(CoreDispatcherPriority.Normal, () => action());
|
||||
#else
|
||||
|
@ -144,5 +178,13 @@ namespace GalaSoft.MvvmLight.Threading
|
|||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the class by deleting the <see cref="UIDispatcher"/>
|
||||
/// </summary>
|
||||
public static void Reset()
|
||||
{
|
||||
UIDispatcher = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,60 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Windows.Controls;
|
||||
using System.Threading;
|
||||
using System.Windows.Controls;
|
||||
using GalaSoft.MvvmLight.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace GalaSoft.MvvmLight.Test.Threading
|
||||
{
|
||||
[TestClass]
|
||||
public class TestDispatcherHelper
|
||||
public class DispatcherHelperTest
|
||||
{
|
||||
private const string NewContent = "New content";
|
||||
private Button _button;
|
||||
|
||||
[TestMethod]
|
||||
public void TestDispatchingToUiThread()
|
||||
{
|
||||
_button = new Button
|
||||
{
|
||||
Content = "Content1"
|
||||
};
|
||||
|
||||
var manualEvent = new ManualResetEvent(false);
|
||||
|
||||
var thread = new Thread(() =>
|
||||
{
|
||||
Thread.Sleep(500);
|
||||
DispatcherHelper.CheckBeginInvokeOnUI(() =>
|
||||
{
|
||||
AccessMethodOnUiThread(NewContent);
|
||||
manualEvent.Set();
|
||||
});
|
||||
});
|
||||
|
||||
DispatcherHelper.Initialize();
|
||||
|
||||
thread.Start();
|
||||
|
||||
manualEvent.WaitOne(1000);
|
||||
|
||||
#if SILVERLIGHT
|
||||
// No way to verify that the button is correctly set
|
||||
// in WPF, however the mere fact that we didn't get an exception
|
||||
// is an indication of success.
|
||||
DispatcherHelper.UIDispatcher.BeginInvoke(VerifyButtonNewContent);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void AccessMethodOnUiThread(string newContent)
|
||||
{
|
||||
_button.Content = newContent;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestDirectAccessToUiThread()
|
||||
{
|
||||
|
@ -67,18 +24,124 @@ namespace GalaSoft.MvvmLight.Test.Threading
|
|||
DispatcherHelper.CheckBeginInvokeOnUI(() => _button.Content = NewContent);
|
||||
|
||||
#if SILVERLIGHT
|
||||
// No way to verify that the button is correctly set
|
||||
// in WPF, however the mere fact that we didn't get an exception
|
||||
// is an indication of success.
|
||||
// No way to verify that the button is correctly set
|
||||
// in WPF, however the mere fact that we didn't get an exception
|
||||
// is an indication of success.
|
||||
Assert.AreEqual(NewContent, _button.Content);
|
||||
#endif
|
||||
}
|
||||
|
||||
private const string NewContent = "New content";
|
||||
[TestMethod]
|
||||
public void TestDispatchingToUiThread()
|
||||
{
|
||||
_button = new Button
|
||||
{
|
||||
Content = "Content1"
|
||||
};
|
||||
|
||||
var manualEvent = new ManualResetEvent(false);
|
||||
|
||||
var thread = new Thread(
|
||||
() =>
|
||||
{
|
||||
Thread.Sleep(500);
|
||||
DispatcherHelper.CheckBeginInvokeOnUI(
|
||||
() =>
|
||||
{
|
||||
AccessMethodOnUiThread(NewContent);
|
||||
manualEvent.Set();
|
||||
});
|
||||
});
|
||||
|
||||
DispatcherHelper.Initialize();
|
||||
|
||||
thread.Start();
|
||||
|
||||
manualEvent.WaitOne(1000);
|
||||
|
||||
#if SILVERLIGHT
|
||||
// No way to verify that the button is correctly set
|
||||
// in WPF, however the mere fact that we didn't get an exception
|
||||
// is an indication of success.
|
||||
DispatcherHelper.UIDispatcher.BeginInvoke(VerifyButtonNewContent);
|
||||
#endif
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestFailingInitializationInCheckBeginInvokeOnUi()
|
||||
{
|
||||
DispatcherHelper.Reset();
|
||||
var done = false;
|
||||
Exception receivedException = null;
|
||||
|
||||
try
|
||||
{
|
||||
DispatcherHelper.CheckBeginInvokeOnUI(
|
||||
() =>
|
||||
{
|
||||
done = true;
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
receivedException = ex;
|
||||
}
|
||||
|
||||
CheckException(receivedException);
|
||||
Assert.IsFalse(done);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestFailingInitializationInRunAsync()
|
||||
{
|
||||
DispatcherHelper.Reset();
|
||||
var done = false;
|
||||
Exception receivedException = null;
|
||||
|
||||
try
|
||||
{
|
||||
DispatcherHelper.RunAsync(
|
||||
() =>
|
||||
{
|
||||
done = true;
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
receivedException = ex;
|
||||
}
|
||||
|
||||
CheckException(receivedException);
|
||||
Assert.IsFalse(done);
|
||||
}
|
||||
|
||||
private void AccessMethodOnUiThread(string newContent)
|
||||
{
|
||||
_button.Content = newContent;
|
||||
}
|
||||
|
||||
private void CheckException(Exception receivedException)
|
||||
{
|
||||
Assert.IsNotNull(receivedException);
|
||||
Assert.AreEqual(typeof (InvalidOperationException), receivedException.GetType());
|
||||
|
||||
#if SILVERLIGHT
|
||||
#if WINDOWS_PHONE
|
||||
Assert.IsTrue(receivedException.Message.Contains("Call DispatcherHelper.Initialize() at the end of App.InitializePhoneApplication."));
|
||||
#else
|
||||
Assert.IsTrue(receivedException.Message.Contains("Call DispatcherHelper.Initialize() in Application_Startup (App.xaml.cs)."));
|
||||
#endif
|
||||
#elif NETFX_CORE
|
||||
Assert.IsTrue(receivedException.Message.Contains("Call DispatcherHelper.Initialize() at the end of App.OnLaunched."));
|
||||
#else
|
||||
Assert.IsTrue(
|
||||
receivedException.Message.Contains("Call DispatcherHelper.Initialize() in the static App constructor."));
|
||||
#endif
|
||||
}
|
||||
|
||||
private void VerifyButtonNewContent()
|
||||
{
|
||||
Assert.AreEqual(NewContent, _button.Content);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче