Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
RoyOsherove
authored and
RoyOsherove
committed
Jun 26, 2007
1 parent
23aa596
commit e5117e3
Showing
8 changed files
with
434 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,19 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Runtime.InteropServices; | |||
using System.Security.Permissions; | |||
using System.Text; | |||
using System.Threading; | |||
|
|||
namespace Osherove.ThreadTester.Events | |||
{ | |||
[ComVisible(true), HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)] | |||
public class AutoResetEventEx : EventWaitHandleEx | |||
{ | |||
// Methods | |||
public AutoResetEventEx(bool initialState) | |||
: base(initialState, EventResetMode.AutoReset) | |||
{ | |||
} | |||
} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,148 @@ | |||
using System; | |||
using System.Runtime.InteropServices; | |||
using System.Security.AccessControl; | |||
using System.Security.Permissions; | |||
using System.Threading; | |||
|
|||
namespace Osherove.ThreadTester.Events | |||
{ | |||
|
|||
[ComVisible(true), HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)] | |||
public class EventWaitHandleEx : EventWaitHandle | |||
{ | |||
public delegate void WaitDelegate(object sender, WaitEventArgs args); | |||
public event WaitDelegate BeforeWaitCalled = delegate { }; | |||
public event EventHandler Closed = delegate { }; | |||
|
|||
public EventWaitHandleEx(bool initialState, EventResetMode mode) | |||
: base(initialState, mode) | |||
{ | |||
} | |||
|
|||
|
|||
public override bool WaitOne(TimeSpan timeout, bool exitContext) | |||
{ | |||
bool cancel = false; | |||
OnWait((int?) timeout.TotalMilliseconds, exitContext, ref cancel); | |||
if (cancel) | |||
{ | |||
return false; | |||
} | |||
|
|||
return base.WaitOne(timeout, exitContext); | |||
} | |||
|
|||
public override bool WaitOne(int millisecondsTimeout, bool exitContext) | |||
{ | |||
bool cancel = false; | |||
OnWait(millisecondsTimeout, exitContext, ref cancel); | |||
if (cancel && allowWaitCanceling) | |||
{ | |||
return false; | |||
} | |||
return base.WaitOne(millisecondsTimeout, exitContext); | |||
} | |||
|
|||
|
|||
public override bool WaitOne() | |||
{ | |||
bool cancel = false; | |||
OnWait(null, null,ref cancel); | |||
if (cancel) | |||
{ | |||
return false; | |||
} | |||
return base.WaitOne(); | |||
} | |||
|
|||
|
|||
private bool allowWaitCanceling; | |||
|
|||
/// <summary> | |||
/// Setting this to true will trigger the BeforeWaitCalled event | |||
/// in a synchronized fasion. when false, the event is thrown in asyc (new thread). | |||
/// </summary> | |||
public bool AllowWaitCanceling | |||
{ | |||
get { return allowWaitCanceling; } | |||
set { allowWaitCanceling = value; } | |||
} | |||
|
|||
private void TriggerWaitCalledNewThread(int? timeout, bool? exitContext, ref bool cancel) | |||
{ | |||
|
|||
WaitEventArgs args = new WaitEventArgs(timeout, exitContext); | |||
Thread t = new Thread(new ThreadStart(delegate | |||
{ | |||
SafeTrigger(BeforeWaitCalled, this, args); | |||
if (args.CancelWait) | |||
{ | |||
ArgumentException exception = new ArgumentException("You can't cancel a call to WaitOne() without setting AllowWaitCanceling to true"); | |||
ThreadManager.exceptions.Add(exception); | |||
throw exception; | |||
} | |||
})); | |||
t.Start(); | |||
} | |||
private static void SafeTrigger(Delegate del, params object[] args) | |||
{ | |||
// // return; | |||
// del.DynamicInvoke(args); | |||
// return; | |||
|
|||
foreach (Delegate callback in del.GetInvocationList()) | |||
{ | |||
try | |||
{ | |||
callback.DynamicInvoke(args); | |||
} | |||
catch (Exception e) | |||
{ | |||
// Console.WriteLine(e.ToString()); | |||
} | |||
} | |||
} | |||
private void TriggerWaitCalledSameThread(int? timeout, bool? exitContext, ref bool cancel) | |||
{ | |||
WaitEventArgs args = new WaitEventArgs(timeout, exitContext); | |||
SafeTrigger(BeforeWaitCalled, this, args); | |||
if (args.CancelWait) | |||
{ | |||
cancel = true; | |||
} | |||
} | |||
private int waiters; | |||
|
|||
public int Waiters | |||
{ | |||
get { return waiters; } | |||
set { waiters = value; } | |||
} | |||
|
|||
private void OnWait(int? timeout, bool? exitContext, ref bool cancel) | |||
{ | |||
|
|||
waiters++; | |||
if (allowWaitCanceling) | |||
{ | |||
TriggerWaitCalledSameThread(timeout, exitContext, ref cancel); | |||
if(cancel) | |||
{ | |||
waiters--; | |||
} | |||
} | |||
else | |||
{ | |||
TriggerWaitCalledNewThread(timeout, exitContext, ref cancel); | |||
} | |||
|
|||
} | |||
|
|||
|
|||
|
|||
} | |||
|
|||
|
|||
|
|||
|
|||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,18 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Runtime.InteropServices; | |||
using System.Security.Permissions; | |||
using System.Text; | |||
using System.Threading; | |||
|
|||
namespace Osherove.ThreadTester.Events | |||
{ | |||
// | |||
public class ManualResetEventEx : EventWaitHandleEx | |||
{ | |||
public ManualResetEventEx(bool initialState) | |||
: base(initialState, EventResetMode.ManualReset) | |||
{ | |||
} | |||
} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,30 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
|
|||
namespace Osherove.ThreadTester.Events | |||
{ | |||
public class UnhandledException:Exception | |||
{ | |||
private object sender; | |||
private UnhandledExceptionEventArgs args; | |||
|
|||
public UnhandledException(object sender, UnhandledExceptionEventArgs args) | |||
{ | |||
this.sender = sender; | |||
this.args = args; | |||
} | |||
|
|||
public object Sender | |||
{ | |||
get { return sender; } | |||
set { sender = value; } | |||
} | |||
|
|||
public UnhandledExceptionEventArgs Args | |||
{ | |||
get { return args; } | |||
set { args = value; } | |||
} | |||
} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,47 @@ | |||
using System; | |||
|
|||
namespace Osherove.ThreadTester.Events | |||
{ | |||
public class WaitEventArgs:EventArgs | |||
{ | |||
private bool cancelwait; | |||
|
|||
public bool CancelWait | |||
{ | |||
get { return cancelwait; } | |||
set { cancelwait = value; } | |||
} | |||
|
|||
private int? timeout; | |||
|
|||
public int? TimeOut | |||
{ | |||
get { return timeout; } | |||
set { timeout = value; } | |||
} | |||
|
|||
private bool? exitContext; | |||
|
|||
public bool? ExitContext | |||
{ | |||
get { return exitContext; } | |||
set { exitContext = value; } | |||
} | |||
|
|||
public WaitEventArgs() | |||
{ | |||
} | |||
|
|||
|
|||
public WaitEventArgs(int? timeout) | |||
{ | |||
this.timeout = timeout; | |||
} | |||
|
|||
public WaitEventArgs(int? timeout, bool? exitContext) | |||
{ | |||
this.timeout = timeout; | |||
this.exitContext = exitContext; | |||
} | |||
} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,5 @@ | |||
|
|||
1.00.1 | |||
---------- | |||
- Added ResetAbort() to threads to prevent ugly exceptions | |||
- Added .StopWhenTrue() ability |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,55 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using NUnit.Framework; | |||
using Osherove.ThreadTester.Events; | |||
|
|||
namespace Osherove.ThreadTester.Tests | |||
{ | |||
[TestFixture] | |||
public class EventWaitHandleExTests | |||
{ | |||
[Test] | |||
// [ExpectedException(typeof(ArgumentException), "You can't cancel a call to WaitOne() without setting AllowWaitCanceling to true")] | |||
public void WaitOne_CancelSetToTrueOnEvent_CanCancelWait() | |||
{ | |||
AutoResetEventEx e = new AutoResetEventEx(false); | |||
e.BeforeWaitCalled+=delegate(object sender, WaitEventArgs args) | |||
{ | |||
args.CancelWait = true; | |||
}; | |||
e.WaitOne(100, true); | |||
Assert.AreEqual(1,ThreadManager.exceptions.Count); | |||
|
|||
} | |||
|
|||
[Test] | |||
public void BeforeWaitCalled_Triggered() | |||
{ | |||
AutoResetEventEx e = new AutoResetEventEx(false); | |||
e.BeforeWaitCalled += delegate(object sender, WaitEventArgs args) | |||
{ | |||
Assert.AreEqual(100,args.TimeOut); | |||
Assert.AreEqual(true,args.ExitContext); | |||
Console.WriteLine("wait({0},{1})", args.TimeOut, args.ExitContext); | |||
}; | |||
bool result = e.WaitOne(100, true); | |||
Assert.AreEqual(1, e.Waiters); | |||
Console.WriteLine("done"); | |||
} | |||
|
|||
[Test] | |||
public void BeforeWaitCalled_TriggeredAndCancenled() | |||
{ | |||
AutoResetEventEx e = new AutoResetEventEx(false); | |||
e.AllowWaitCanceling = true; | |||
e.BeforeWaitCalled += delegate(object sender, WaitEventArgs args) | |||
{ | |||
args.CancelWait = true; | |||
}; | |||
bool result = e.WaitOne(1000, true); | |||
Assert.AreEqual(0,e.Waiters); | |||
Console.WriteLine("done"); | |||
} | |||
} | |||
} |
Oops, something went wrong.