Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Sometimes you work with an API that returns a Choice. If you want to add a timeout to any choice we need to extend the set of extension methods I introduced in part 22 with this:
1: public static class ChoiceWithTimeoutExtenstions
2: {
3: private static DispatcherQueue taskQueue = new DispatcherQueue();
4:
5: public static TimeSpan DefaultTimeout { get; set; }
6:
7: static ChoiceWithTimeoutExtenstions()
8: {
9: DefaultTimeout = TimeSpan.FromSeconds(30);
10: }
11:
12: public static Choice WithTimeout(
13: this Choice choice,
14: Handler<DateTime> timeoutHandler)
15: {
16: return choice.WithTimeout(timeoutHandler, DefaultTimeout);
17: }
18:
19: public static Choice WithTimeout(
20: this Choice choice,
21: Handler<DateTime> timeoutHandler,
22: TimeSpan timeout)
23: {
24: var choiceCompletedPort = new Port<EmptyValue>();
25: Arbiter.Activate(
26: taskQueue,
27: Arbiter.FromIteratorHandler(
28: () => ExecuteChoice(choice, choiceCompletedPort)));
29: var timeoutPort = new Port<DateTime>();
30: taskQueue.EnqueueTimer(timeout, timeoutPort);
31:
32: return Arbiter.Choice(
33: choiceCompletedPort.Receive(),
34: timeoutPort.Receive(dt => timeoutHandler(dt)));
35: }
36:
37: private static IEnumerator<ITask> ExecuteChoice(
38: Choice choice,
39: Port<EmptyValue> port)
40: {
41: yield return choice;
42: port.Post(EmptyValue.SharedInstance);
43: }
44: }
And the test to show how it works:
45: [TestMethod]
46: public void AddingTimeoutToChoice_Timeout()
47: {
48: ChoiceWithTimeoutExtenstions.DefaultTimeout = TimeSpan.FromSeconds(5);
49: var port = new SuccessFailurePort();
50: Exception error = null;
51: bool successReported = false;
52: Arbiter.Activate(
53: dispatcherQueue,
54: port.Choice(s => successReported = true, e => error = e)
55: .WithTimeout(_ => port.Post(new TimeoutException())));
56: Thread.Sleep(TimeSpan.FromSeconds(10));
57: Assert.IsNotNull(error);
58: Assert.IsInstanceOfType(error, typeof(TimeoutException));
59: Assert.IsFalse(successReported);
60: port.Post(SuccessResult.Instance);
61: Thread.Sleep(TimeSpan.FromSeconds(5));
62: Assert.IsFalse(successReported);
63: }
And some example code:
64: public static IEnumerator<ITask> TimeoutOnAnyChoice<T1, T2>(
65: PortSet<T1, T2> port)
66: {
67: yield return
68: port.Choice(
69: a => Console.WriteLine("A: {0}", a),
70: b => Console.WriteLine("B: {0}", b)).WithTimeout(
71: _ => port.PostUnknownType(
72: new TimeoutException("Timeout waiting for choice.")));
73: }