网上演练
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
4.7 KiB

#if FAT
using System;
using System.Threading;
using LinqInternal.Core;
namespace LinqInternal.Threading.Needles
{
[Serializable]
[System.Diagnostics.DebuggerNonUserCode]
internal class LazyAction : Promise
{
[NonSerialized]
private Thread _runnerThread;
private Action _action;
public LazyAction()
: base(true)
{
_action = null;
}
public LazyAction(Action action)
: base(false)
{
if (action == null)
{
throw new ArgumentNullException("action");
}
_action = action;
}
public LazyAction(Action action, bool cacheExceptions)
: base(false)
{
if (action == null)
{
throw new ArgumentNullException("action");
}
_action = action;
if (cacheExceptions)
{
_action = () =>
{
try
{
action.Invoke();
}
catch (Exception exc)
{
_action = ActionHelper.GetThrowAction(exc);
throw;
}
};
}
}
protected Thread RunnerThread
{
get { return _runnerThread; }
}
public virtual void Execute()
{
if (_runnerThread == Thread.CurrentThread)
{
throw new InvalidOperationException();
}
var action = Interlocked.Exchange(ref _action, null);
if (action == null)
{
base.Wait();
}
else
{
ExecuteExtracted(action);
}
}
public void ReleaseAction()
{
Volatile.Write(ref _action, null);
}
public override void Wait()
{
if (_runnerThread == Thread.CurrentThread)
{
throw new InvalidOperationException();
}
base.Wait();
}
public override void Wait(CancellationToken cancellationToken)
{
if (_runnerThread == Thread.CurrentThread)
{
throw new InvalidOperationException();
}
base.Wait(cancellationToken);
}
public override void Wait(int milliseconds)
{
if (_runnerThread == Thread.CurrentThread)
{
throw new InvalidOperationException();
}
base.Wait(milliseconds);
}
public override void Wait(TimeSpan timeout)
{
if (_runnerThread == Thread.CurrentThread)
{
throw new InvalidOperationException();
}
base.Wait(timeout);
}
public override void Wait(int milliseconds, CancellationToken cancellationToken)
{
if (_runnerThread == Thread.CurrentThread)
{
throw new InvalidOperationException();
}
base.Wait(milliseconds, cancellationToken);
}
public override void Wait(TimeSpan timeout, CancellationToken cancellationToken)
{
if (_runnerThread == Thread.CurrentThread)
{
throw new InvalidOperationException();
}
base.Wait(timeout, cancellationToken);
}
protected virtual void Execute(Action beforeInitialize)
{
if (beforeInitialize == null)
{
throw new ArgumentNullException("beforeInitialize");
}
if (_runnerThread == Thread.CurrentThread)
{
throw new InvalidOperationException();
}
var valueFactory = Interlocked.Exchange(ref _action, null);
if (valueFactory == null)
{
base.Wait();
}
else
{
try
{
beforeInitialize.Invoke();
}
finally
{
ExecuteExtracted(valueFactory);
}
}
}
private void ExecuteExtracted(Action action)
{
_runnerThread = Thread.CurrentThread;
try
{
action.Invoke();
}
catch (Exception exception)
{
Interlocked.CompareExchange(ref _action, action, null);
SetError(exception);
throw;
}
finally
{
_runnerThread = null;
}
}
}
}
#endif