- mtvt_2010_5_1__12_15.zip
- Libraries
- DanielVaughan
- Prism
- Silverlight
- Microsoft.Practices.Composite.dll
- Microsoft.Practices.Composite.pdb
- Microsoft.Practices.Composite.Presentation.dll
- Microsoft.Practices.Composite.Presentation.pdb
- Microsoft.Practices.ServiceLocation.dll
- System.Windows.Controls.dll
- Mtvt
- DanielVaughan.Mtvt.sln
- DanielVaughan.Mtvt.suo
- DanielVaughan.Mtvt.vsmdi
- DanielVaughan.MtvtExample.Tests
- DanielVaughan.MtvtExample.Web
- DanielVaughan.MtvtExample
- Local.testsettings
- TraceAndTestImpact.testsettings
- Prism
- CAL
- CAL.vsmdi
- CompositeApplicationLibrary.4.5.resharper.user
- CompositeApplicationLibrary.sln
- CompositeApplicationLibrary_Desktop.4.5.resharper.user
- CompositeApplicationLibrary_Desktop.sln
- Desktop
- Composite.Presentation
- Composite
- LocalTestRun.testrunconfig
- Silverlight
- Composite.Presentation
- Bin
- Commands
- Composite.Presentation.Silverlight.csproj
- Composite.Presentation.Silverlight.csproj.user
- Events
- GlobalSuppressions.cs
- Migrated rules for Composite.Presentation.Silverlight.ruleset
- obj
- Debug
- build.force
- Composite.Presentation.Silverlight.csproj.FileListAbsolute.txt
- Composite.Presentation.Silverlight.csproj.GenerateResource.Cache
- DesignTimeResolveAssemblyReferencesInput.cache
- Microsoft.Practices.Composite.Presentation.dll
- Microsoft.Practices.Composite.Presentation.pdb
- Microsoft.Practices.Composite.Presentation.Properties.Resources.resources
- ResGen.read.1.tlog
- ResGen.write.1.tlog
- ResolveAssemblyReference.cache
- TempPE
- Release
- Composite.Presentation.Silverlight.csproj.FileListAbsolute.txt
- Composite.Presentation.Silverlight.csproj.GenerateResource.Cache
- Microsoft.Practices.Composite.Presentation.dll
- Microsoft.Practices.Composite.Presentation.pdb
- Microsoft.Practices.Composite.Presentation.Properties.Resources.resources
- ResolveAssemblyReference.cache
- TempPE
- Properties
- Regions
- Composite
- LIB
- Silverlight
- ServiceLocation
- Microsoft.Practices.ServiceLocation.dll
|
#region File and License Information
/*
<File>
<Copyright>Copyright © 2009, Daniel Vaughan. All rights reserved.</Copyright>
<License>
This file is part of DanielVaughan's base library
DanielVaughan's base library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DanielVaughan's base library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with DanielVaughan's base library. If not, see http://www.gnu.org/licenses/.
</License>
<Owner Name="Daniel Vaughan" Email="dbvaughan@gmail.com"/>
<CreationDate>2010-04-22 17:26:58Z</CreationDate>
</File>
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using DanielVaughan.Collections;
namespace DanielVaughan.Concurrency
{
/// <summary>
/// Indicates the manner in which delegates are invoked.
/// </summary>
public enum DelegateInvocationMode
{
/// <summary>
/// Delegates are sent to the thread.
/// </summary>
Blocking,
/// <summary>
/// Delegates are posted to the thread.
/// </summary>
NonBlocking
}
/// <summary>
/// Managers a collection of <see cref="Delegate"/> instances.
/// Allows Delegates to be referenced directly
/// or using a <see cref="WeakReference"/>.
/// Allows Delegates to be handled on the thread of subscription.
/// </summary>
public class DelegateManager
{
readonly bool preserveThreadAffinity;
readonly DelegateInvocationMode invocationMode;
readonly IProvider<ISynchronizationContext> contextProvider;
readonly bool useWeakReferences = true;
readonly List<DelegateReference> delegateReferences = new List<DelegateReference>();
readonly object membersLock = new object();
readonly Dictionary<DelegateReference, ISynchronizationContext> synchronizationContexts
= new Dictionary<DelegateReference, ISynchronizationContext>();
/// <summary>Initializes a new instance
/// of the <see cref="DelegateManager"/> class.</summary>
/// <param name="preserveThreadAffinity">If set to <c>true</c>,
/// delegate invocation will occur using the <see cref="ISynchronizationContext"/>
/// provided by the specified context provider.</param>
/// <param name="useWeakReferences">If <c>true</c> weak references will be used.</param>
/// <param name="invocationMode">The invocation mode.
/// If <c>Blocking</c> delegates will be invoked
/// in serial, other in parallel.</param>
/// <param name="contextProvider">The context provider,
/// which is used to supply a context when a delegate is added.
/// If preservedThreadAffinity is <c>false</c>, this value will be ignored.</param>
public DelegateManager(bool preserveThreadAffinity = false,
bool useWeakReferences = false,
DelegateInvocationMode invocationMode = DelegateInvocationMode.Blocking,
IProvider<ISynchronizationContext> contextProvider = null)
{
this.preserveThreadAffinity = preserveThreadAffinity;
this.invocationMode = invocationMode;
this.contextProvider = contextProvider;
this.useWeakReferences = useWeakReferences;
if (contextProvider == null)
{
this.contextProvider = new SynchronizationContextProvider();
}
}
/// <summary>
/// Adds the specified target delegate to the list of delegates
/// that are invoked when <see cref="InvokeDelegates"/> is called.
/// </summary>
/// <param name="targetDelegate">The target delegate.</param>
public void Add(Delegate targetDelegate)
{
ArgumentValidator.AssertNotNull(targetDelegate, "targetDelegate");
var reference = new DelegateReference(targetDelegate, useWeakReferences);
lock (membersLock)
{
delegateReferences.Add(reference);
if (preserveThreadAffinity)
{
synchronizationContexts[reference] = contextProvider.ProvidedItem;
}
}
}
/// <summary>
/// Removes the specified target delegate from the list of delegates.
/// </summary>
/// <param name="targetDelegate">The target delegate.</param>
public void Remove(Delegate targetDelegate)
{
lock (membersLock)
{
var removedItems = delegateReferences.RemoveAll(
reference =>
{
Delegate target = reference.Delegate;
return target == null || targetDelegate.Equals(target);
});
if (preserveThreadAffinity)
{
foreach (var delegateReference in removedItems)
{
synchronizationContexts.Remove(delegateReference);
}
}
}
}
/// <summary>
/// Invokes each delegate.
/// </summary>
/// <param name="args">The args included during delegate invocation.</param>
/// <exception cref="Exception">
/// Rethrown exception if a delegate invocation raises an exception.
/// </exception>
public void InvokeDelegates(params object[] args)
{
IEnumerable<DelegateReference> delegates;
/* Retrieve the valid delegates by first trim
* the collection of null delegates. */
lock (membersLock)
{
var removedItems = delegateReferences.RemoveAll(
listener => listener.Delegate == null);
if (preserveThreadAffinity)
{
/* Clean the synchronizationContexts of those removed
* in the preceding step. */
foreach (var delegateReference in removedItems)
{
synchronizationContexts.Remove(delegateReference);
}
}
/* The lock prevents changes to the collection,
* therefore we can safely compile our list. */
delegates = (from reference in delegateReferences
select reference).ToList();
}
/* At this point any changes to the delegateReferences collection
* won't be noticed. */
foreach (var reference in delegates)
{
if (!preserveThreadAffinity)
{
reference.Delegate.DynamicInvoke(args);
continue;
}
var context = synchronizationContexts[reference];
DelegateReference referenceInsideCloser = reference;
Exception exception = null;
var callback = new SendOrPostCallback(
delegate
{
try
{
referenceInsideCloser.Delegate.DynamicInvoke(args);
}
catch (Exception ex)
{
exception = ex;
}
});
switch (invocationMode)
{
case DelegateInvocationMode.Blocking:
context.InvokeAndBlockUntilCompletion(callback, null);
break;
case DelegateInvocationMode.NonBlocking:
context.InvokeWithoutBlocking(callback, null);
break;
default:
throw new ArgumentOutOfRangeException("Unknown DispatchMode: "
+ invocationMode.ToString("G"));
}
/* Rethrowing the exception may be missed
* in a DispatchMode.Post scenario. */
if (exception != null)
{
throw exception;
}
}
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Daniel is a former senior engineer in Technology and Research at the Office of the CTO at Microsoft, working on next generation systems.
Previously Daniel was a nine-time Microsoft MVP and co-founder of
Outcoder, a Swiss software and consulting company.
Daniel is the author of Windows Phone 8 Unleashed and Windows Phone 7.5 Unleashed, both published by SAMS.
Daniel is the developer behind several acclaimed mobile apps including
Surfy Browser for Android and Windows Phone. Daniel is the creator of a number of popular open-source projects, most notably
Codon.
Would you like Daniel to bring value to your organisation?
Please contact
Blog |
Twitter
Xamarin Experts
Windows 10 Experts