CSLA.NET 6.0.0
CSLA .NET is a software development framework that helps you build a reusable, maintainable object-oriented business layer for your app.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
BackgroundWorkerSyncContextHelper.cs
Go to the documentation of this file.
1//using System;
2//using System.Collections;
3//using System.Collections.Generic;
4//using System.Collections.ObjectModel;
5//using System.Collections.Specialized;
6//using System.ComponentModel;
7//using System.Diagnostics;
8//using System.Linq;
9//using System.Reflection;
10//using System.Threading;
11//using System.Windows.Threading;
12
13//namespace Csla.Test.Threading
14//{
15// /// <summary>
16// /// Helps ensure the proper behaviour of the BackgroundWorker.
17// ///
18// /// Backgroundworker makes heavy use of the AsyncOperationManager & SynchronisationContext. When the default
19// /// SynchronisationContext is used, it just invokes to callbacks on the current thread, not the UI thread.
20// ///
21// /// To ensure real world testability of items using this class, we're using a dispatcher (a WPF, but UI Agnostic
22// /// class) to provide the ability to call back into the thread that starts it.
23// ///
24// /// Dispatchers are a message pump, so block on their RunMethod -- this means we need to spin up our own thread, an
25// /// queue items into that as tests that are synchronously invoked.
26// /// </summary>
27// public class BackgroundWorkerSyncContextHelper
28// {
29// private static Thread m_dispatcherThread;
30// private static Dispatcher m_dispatcher;
31// private static ManualResetEvent m_dispatcherSetup = new ManualResetEvent(false);
32// private static Stack<Exception> s_exceptionQueue = new Stack<Exception>();
33
34// public static void Init()
35// {
36// // Create the thread, and start it, and wait for it to complete init before
37// // returning and allowing people to invoke tests on the disptacher
38// m_dispatcherThread = new Thread(CreateDispatcher);
39// m_dispatcherThread.Name = "Test Disptacher Thread";
40// m_dispatcherThread.SetApartmentState(ApartmentState.STA);
41// m_dispatcherThread.Start();
42// m_dispatcherSetup.WaitOne();
43// }
44
45// /// <summary>
46// /// Creates thedispatcher, and hooks up the unhandled exception handler
47// /// Starts executing the dispatcher and blocks.
48// /// </summary>
49// private static void CreateDispatcher()
50// {
51// m_dispatcher = Dispatcher.CurrentDispatcher;
52// m_dispatcher.UnhandledException += new DispatcherUnhandledExceptionEventHandler(m_dispatcher_UnhandledException);
53// AsyncOperationManager.SynchronizationContext = new DispatcherSynchronizationContext(m_dispatcher);
54
55// m_dispatcherSetup.Set();
56// Dispatcher.Run();
57// }
58
59// /// <summary>
60// /// Handle all the "unhandled" exceptions on the dispatcher, and allow them to be dequeued later to show
61// /// the assertions/errors on the Test Thread
62// /// </summary>
63// private static void m_dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
64// {
65// // Don't let the dispatcher die, handle the exception always.
66// e.Handled = true;
67
68// // We likely want the real innerexception, not some top-level TargetInvokation exception. Get the exception
69// // and queue.
70// if (e.Exception.InnerException == null)
71// {
72// s_exceptionQueue.Push(e.Exception);
73// }
74// else
75// {
76// s_exceptionQueue.Push(e.Exception.InnerException);
77// }
78
79// // We want the exceptions we see to be logged rather than dumped into the ether.
80// Console.WriteLine("Exception found during execution:");
81// Console.WriteLine(s_exceptionQueue.Peek().ToString());
82// }
83
84// /// <summary>
85// /// clears any exceptions so as not to confuse other tests.
86// /// </summary>
87// public static void ClearException()
88// {
89// s_exceptionQueue.Clear();
90// }
91
92// /// <summary>
93// /// Dumps all the queued exceptions, and *throws* the last exception that was thrown
94// /// </summary>
95// public static void DumpExceptionsAndThrow()
96// {
97// // Just return if we dont have any exceptions
98// if (s_exceptionQueue.Count < 1)
99// {
100// return;
101// }
102
103// // Dump the exceptions as strings to the log for people to see.
104// Console.WriteLine("Dumping Exceptions seen while executing:");
105// while (s_exceptionQueue.Count > 1)
106// {
107// Exception e = s_exceptionQueue.Pop();
108// Console.WriteLine(e.ToString());
109// }
110
111// // Dumps the last exception that was thrown, and then throws it (breaks the callstack... sorry)
112// Exception last = s_exceptionQueue.Pop();
113// Console.WriteLine("Last Exception that was thrown:");
114// Console.WriteLine(last.ToString());
115
116// throw last;
117// }
118
119// /// <summary>
120// /// Shuts town the disptacher thread for a clean shutdown.
121// /// </summary>
122// public static void Cleanup()
123// {
124// m_dispatcher.InvokeShutdown();
125// }
126
127// public static Dispatcher Dispatcher
128// {
129// get { return m_dispatcher; }
130// }
131
132// public static event ThreadStart TestInitialize;
133
134// public static event ThreadStart TestCleanup;
135
136// public static void DoTests(Action test)
137// {
138// BackgroundWorkerSyncContextHelper.ClearException();
139// BackgroundWorkerSyncContextHelper.Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, new ThreadStart(delegate()
140// {
141// try
142// {
143// if (TestInitialize != null)
144// {
145// TestInitialize();
146// }
147
148// test();
149// }
150// finally
151// {
152// if (TestCleanup != null)
153// {
154// TestCleanup();
155// }
156// }
157// }));
158
159// DumpExceptionsAndThrow();
160// }
161
162// public static void PumpDispatcher()
163// {
164// // This is dispatcher magic. I'm not 100% sure how it works, but this is the karmic equiv. of
165// // Application.DoEvents() in the Winforms world, and allows any items in the dispatchers queue to be processed
166// DispatcherFrame f = new DispatcherFrame();
167// Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new DispatcherOperationCallback((p) =>
168// {
169// ((DispatcherFrame)p).Continue = false;
170// return null;
171// }), f);
172
173// Dispatcher.PushFrame(f);
174// }
175// }
176//}