Konstantin Koch 8287c54432 Included the Visual Studio extension and made the necessary changes to make it run.
Replaced the old VS templates with ones that offer more flexiblity.
Started replacing the Content Project for the samples with our custom project type.
Inlcuded a basic not yet working AssimpImporter.
2015-04-08 14:50:03 +02:00

243 lines
9.2 KiB
C#

/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* vspython@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
* ***************************************************************************/
namespace Microsoft.VisualStudio.Project
{
using System;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using System.Windows.Forms;
public sealed class UIThread : IDisposable
{
private WindowsFormsSynchronizationContext synchronizationContext;
private bool isUnitTestingMode;
private Thread uithread;
#if DEBUG
/// <summary>
/// Stack trace when synchronizationContext was captured
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
private StackTrace captureStackTrace;
#endif
/// <summary>
/// RunSync puts orignal exception stacktrace to Exception.Data by this key if action throws on UI thread
/// </summary>
/// WrappedStacktraceKey is a string to keep exception serializable.
private const string WrappedStacktraceKey = "$$Microsoft.VisualStudio.Package.UIThread.WrappedStacktraceKey$$";
/// <summary>
/// The singleton instance.
/// </summary>
private static volatile UIThread instance = new UIThread();
public UIThread()
{
this.Initialize();
}
/// <summary>
/// Gets the singleton instance
/// </summary>
public static UIThread Instance
{
get
{
return instance;
}
}
/// <summary>
/// Checks whether this is the UI thread.
/// </summary>
public bool IsUIThread
{
get { return this.uithread == System.Threading.Thread.CurrentThread; }
}
#region IDisposable Members
/// <summary>
/// Dispose implementation.
/// </summary>
public void Dispose()
{
if (this.synchronizationContext != null)
{
this.synchronizationContext.Dispose();
}
}
#endregion
/// <summary>
/// Initializes unit testing mode for this object
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
public void InitUnitTestingMode()
{
Debug.Assert(this.synchronizationContext == null, "Context has already been captured; too late to InitUnitTestingMode");
this.isUnitTestingMode = true;
}
[Conditional("DEBUG")]
public void MustBeCalledFromUIThread()
{
Debug.Assert(this.uithread == System.Threading.Thread.CurrentThread || this.isUnitTestingMode, "This must be called from the GUI thread");
}
/// <summary>
/// Runs an action asynchronously on an associated forms synchronization context.
/// </summary>
/// <param name="a">The action to run</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
public void Run(Action a)
{
if (this.isUnitTestingMode)
{
a();
return;
}
Debug.Assert(this.synchronizationContext != null, "The SynchronizationContext must be captured before calling this method");
#if DEBUG
StackTrace stackTrace = new StackTrace(true);
#endif
this.synchronizationContext.Post(delegate(object ignore) {
try
{
this.MustBeCalledFromUIThread();
a();
}
#if DEBUG
catch (Exception e)
{
// swallow, random exceptions should not kill process
Debug.Assert(false, string.Format(CultureInfo.InvariantCulture, "UIThread.Run caught and swallowed exception: {0}\n\noriginally invoked from stack:\n{1}", e.ToString(), stackTrace.ToString()));
}
#else
catch (Exception)
{
// swallow, random exceptions should not kill process
}
#endif
}, null);
}
/// <summary>
/// Runs an action synchronously on an associated forms synchronization context
/// </summary>
/// <param name="a">The action to run.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
public void RunSync(Action a)
{
// if we're already on the UI thread run immediately - this prevents
// re-entrancy at unexpected times when we're already on the UI thread.
if (this.isUnitTestingMode ||
uithread == Thread.CurrentThread)
{
a();
return;
}
Exception exn = null; ;
Debug.Assert(this.synchronizationContext != null, "The SynchronizationContext must be captured before calling this method");
// Send on UI thread will execute immediately.
this.synchronizationContext.Send(ignore => {
try
{
this.MustBeCalledFromUIThread();
a();
}
catch (Exception e)
{
exn = e;
}
}, null
);
if (exn != null)
{
// throw exception on calling thread, preserve stacktrace
if (!exn.Data.Contains(WrappedStacktraceKey)) exn.Data[WrappedStacktraceKey] = exn.StackTrace;
throw exn;
}
}
/// <summary>
/// Runs an action synchronously on an associated forms synchronization context
/// </summary>
/// <typeparam name="T">Return type</typeparam>
/// <param name="a">The function</param>
/// <returns></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
public T RunSync<T>(Func<T> a) {
T retValue = default(T);
if (this.isUnitTestingMode) {
return a();
}
Exception exn = null; ;
Debug.Assert(this.synchronizationContext != null, "The SynchronizationContext must be captured before calling this method");
// Send on UI thread will execute immediately.
this.synchronizationContext.Send(ignore => {
try {
this.MustBeCalledFromUIThread();
retValue = a();
} catch (Exception e) {
exn = e;
}
}, null
);
if (exn != null) {
// throw exception on calling thread, preserve stacktrace
if (exn.Data != null && !exn.Data.Contains(WrappedStacktraceKey)) exn.Data[WrappedStacktraceKey] = exn.StackTrace;
throw exn;
}
return retValue;
}
/// <summary>
/// Initializes this object.
/// </summary>
private void Initialize()
{
if (this.isUnitTestingMode) return;
this.uithread = System.Threading.Thread.CurrentThread;
if (this.synchronizationContext == null)
{
#if DEBUG
// This is a handy place to do this, since the product and all interesting unit tests
// must go through this code path.
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(delegate(object sender, UnhandledExceptionEventArgs args) {
if (args.IsTerminating)
{
string s = String.Format(CultureInfo.InvariantCulture, "An unhandled exception is about to terminate the process. Exception info:\n{0}", args.ExceptionObject.ToString());
Debug.Assert(false, s);
}
});
this.captureStackTrace = new StackTrace(true);
#endif
this.synchronizationContext = new WindowsFormsSynchronizationContext();
}
else
{
// Make sure we are always capturing the same thread.
Debug.Assert(this.uithread == Thread.CurrentThread);
}
}
}
}