public Task ExecuteAsync(Command <M> command) { var response = new WriteOnceBlock <object>(b => b); _journaler.Post(new CommandRequest(command, response)); return(response.ReceiveAsync()); }
public void AsyncReceiveTestCanceled() { var src = new CancellationTokenSource(); var block = new WriteOnceBlock <int> (null); var task = block.ReceiveAsync(src.Token); Task.Factory.StartNew(() => { Thread.Sleep(800); block.Post(42); }); Thread.Sleep(50); src.Cancel(); AggregateException ex = null; try { task.Wait(); } catch (AggregateException e) { ex = e; } Assert.IsNotNull(ex); Assert.IsNotNull(ex.InnerException); Assert.IsInstanceOfType(typeof(OperationCanceledException), ex.InnerException); Assert.IsTrue(task.IsCompleted); Assert.AreEqual(TaskStatus.Canceled, task.Status); }
public async Task <R> ExecuteAsync <R>(Query <M, R> query) { var response = new WriteOnceBlock <object>(r => r); _executionPipeline.Post(new QueryRequest(query, response)); return((R)await response.ReceiveAsync()); }
public async Task <DiscoveredServerInfo> DiscoverReturnFirstAsync() { Task discoverAllTask = DiscoverAllAsync(); Task <DiscoveredServerInfo> firstTask = m_wbFirstResult.ReceiveAsync(); Task res = await Task.WhenAny(discoverAllTask, firstTask); try { if (res == firstTask) { return(await firstTask); } else { await discoverAllTask; if (FoundServer.Count > 0) { return(FoundServer[0]); } else { return(null); } } } catch (OperationCanceledException) { return(null); } }
public async Task <R> ExecuteAsync <R>(Command <M, R> command) { var response = new WriteOnceBlock <object>(r => r); _journaler.Post(new CommandRequest(command, response)); return((R)await response.ReceiveAsync()); }
public async Task AllDisposeAsync() { //before dispose requestStream need to //wait 60 second to receive 'completed' from client side. await Task.WhenAny(Task.Delay(1000 * 60), _end.ReceiveAsync()); }
// This demonstrates the behavior of the WriteOnceBlock as it's easy to observe. // // Preface: I hate the name of this block. It's misleading. This should have been // called CloneBlock or CacheBlock. WriteOnceBlock sounds like you use the block once // and it then self-destructs. // How it works is simple, it will accept one published message and reject all other messages // coming to it. It will then take the first message and clone it and send it on every request // downstream. private static async Task WriteBlockBehaviorDemoAsync() { Console.WriteLine("WriteOneBlockDemo has started!"); var block = new WriteOnceBlock <string>(input => input); // needs a clone function for (int i = 0; i < 5; i++) { if (block.Post(ProduceTimeData())) { Console.WriteLine($"Message {i} was accepted"); } else { Console.WriteLine($"Message {i} was rejected"); } } // Notice the count is much higher than input count and that I am not // waiting on it to signal no more data is coming, as it always has data. for (int i = 0; i < 15; i++) { var output = await block.ReceiveAsync().ConfigureAwait(false); Console.WriteLine($"ReceivedMessage {i}: {output}"); } block.Complete(); await block.Completion.ConfigureAwait(false); Console.WriteLine("Finished!"); Console.ReadKey(); }
public async Task <ServiceOnceCallParam> GetServiceOnceCallParamAsync() { var requestBody = await _cmdReq.ReceiveAsync(); var ocp = requestBody.ToObject <OnceCallParam>(); //stream ReadStream?rs; if (ocp.HasStream) { if (ocp.PostStream != null) { rs = new ProxyStream(new MemoryStream(ocp.PostStream)); } else { rs = new ProxyStream(_streamPipe.InputStream, ocp.StreamLength, true); } } else { rs = null; } return(new ServiceOnceCallParam(ocp.Action, ocp.PureArgs, ocp.StreamLength, rs, ocp.Header)); }
public async Task <TResult> InvokeAsync() { if (_invoked) { throw new InvalidOperationException("Already invoded."); } _invoked = true; try { var waitTask = _cancelToken != null?_wobResult.ReceiveAsync(_cancelToken.Value) : _wobResult.ReceiveAsync(); Invoke(); var resultTask = await Task.WhenAny(waitTask, Task.Delay(_timeOutMs)); if (resultTask == waitTask) { return(waitTask.Result); } throw new TimeoutException(); } catch (Exception ex) { Exception(ex); return(default(TResult)); } finally { Dispose(); } }
public async Task<string> AskAsync(Question question) { var b = new WriteOnceBlock<string>(s => s); question.answerBlock = b; // TODO: handle if buffer refuses message? If task.Result is false var task = await buf.SendAsync(question); return await b.ReceiveAsync(); }
/// <summary> /// Отправляет NMS-сообщение <paramref name="query"/> и ожидает ответа. /// Асинхронная операция. /// </summary> /// <typeparam name="TMessage">Тип сообщения, потомок NmsMessage.</typeparam> /// <param name="query">Сообщение-запрос.</param> /// <param name="options">Параметры асинхронной операции.</param> /// <returns> /// <see cref="Task{TResult}"/> асинхронная операция - ответное сообщение. /// </returns> /// <exception cref="AggregateException">Призошла ошибка в асинхронном коде. См. <see cref="Exception.InnerException"/></exception> /// <exception cref="TimeoutException">Ошибка по таймауту.</exception> /// <exception cref="TaskCanceledException">Операция прервана пользователем.</exception> /// <exception cref="NibusResponseException">Ошибка NiBUS.</exception> public async Task <TMessage> WaitForNmsResponseAsync <TMessage>(TMessage query, NibusOptions options = null) where TMessage : NmsMessage { //Contract.Requires(!IsDisposed); //Contract.Requires( // query.Datagram.Destanation.Type == AddressType.Hardware // || query.Datagram.Destanation.Type == AddressType.Net); options = GetDefaultOrClone(options); // Последнее сообщение в BroadcastBlock всегда остается! Незабываем его фильтровать. NmsMessage lastMessage; IncomingMessages.TryReceive(null, out lastMessage); var wob = new WriteOnceBlock <NmsMessage>(m => m); using (IncomingMessages.LinkTo( wob, m => !ReferenceEquals(lastMessage, m) && m.IsResponse && m.ServiceType == query.ServiceType && (query.Id == 0 || m.Id == query.Id) && (query.Datagram.Destanation == Address.Empty || m.Datagram.Source == query.Datagram.Destanation))) { for (var i = 0; i < options.Attempts; i++) { await OutgoingMessages.SendAsync(query); try { var response = (TMessage)await wob.ReceiveAsync(options.Timeout, options.Token).ConfigureAwait(false); if (response.ErrorCode != 0) { throw new NibusResponseException(response.ErrorCode); } return(response); } catch (TimeoutException) { Logger.Debug("Timeout {0}", i + 1); if (i < options.Attempts - 1) { continue; } throw; } } } // Эта точка недостижима при attempts > 0! throw new InvalidOperationException(); }
public void AsyncReceiveTest() { int result = -1; var mre = new ManualResetEventSlim(false); var block = new WriteOnceBlock <int> (null); block.ReceiveAsync().ContinueWith(i => { result = i.Result; mre.Set(); }); Task.Factory.StartNew(() => { Thread.Sleep(600); block.Post(42); }); mre.Wait(); Assert.AreEqual(42, result); }
public async Task TestReceiveThenPost() { var wob = new WriteOnceBlock <int>(null); var ignored = Task.Run(() => wob.Post(42)); Assert.Equal(expected: 42, actual: wob.Receive()); // this should always pass, but due to race we may not test what we're hoping to await wob.Completion; wob = new WriteOnceBlock <int>(null); Task <int> t = wob.ReceiveAsync(); Assert.False(t.IsCompleted); wob.Post(16); Assert.Equal(expected: 16, actual: await t); }
public async Task <Match> FindMatchAsync(UserBoard player) { if (!_players.TryAdd(player.Username, player)) { return(null); } var block = new WriteOnceBlock <Match>(null); if (!_blocks.TryAdd(player.Username, block)) { _players.Remove(player.Username); return(null); } LookForMatches(player, block); return(await block.ReceiveAsync()); }
private async Task <NmsRead> GetNmsReadResponseAsync( NmsMessage lastMessage, Address target, int id, NibusOptions options) { var wob = new WriteOnceBlock <NmsMessage>(m => m); using (IncomingMessages.LinkTo( wob, m => !ReferenceEquals(lastMessage, m) && m.IsResponse && m.ServiceType == NmsServiceType.Read && m.Id == id && (target == Address.Empty || m.Datagram.Source == target))) { var response = (NmsRead)await wob.ReceiveAsync(options.Timeout, options.Token).ConfigureAwait(false); if (response.ErrorCode != 0) { throw new NibusResponseException(response.ErrorCode); } return(response); } }
public async Task TestPostThenReceive() { var wob = new WriteOnceBlock <int>(i => i); for (int i = 10; i < 15; i++) { bool posted = wob.Post(i); Assert.Equal(expected: i == 10, actual: posted); } int item; Assert.True(wob.TryReceive(out item)); Assert.Equal(expected: 10, actual: item); await wob.Completion; wob = new WriteOnceBlock <int>(null); wob.Post(42); Task <int> t = wob.ReceiveAsync(); Assert.True(t.IsCompleted); Assert.Equal(expected: 42, actual: t.Result); await wob.Completion; }
public async Task TestCloning() { // Test cloning when a clone function is provided { int data = 42; var wob = new WriteOnceBlock <int>(x => - x); Assert.True(wob.Post(data)); Assert.False(wob.Post(data + 1)); for (int i = 0; i < 3; i++) { int item; Assert.True(wob.TryReceive(out item)); Assert.Equal(expected: -data, actual: item); Assert.Equal(expected: -data, actual: wob.Receive()); Assert.Equal(expected: -data, actual: await wob.ReceiveAsync()); IList <int> items; Assert.True(((IReceivableSourceBlock <int>)wob).TryReceiveAll(out items)); Assert.Equal(expected: items.Count, actual: 1); Assert.Equal(expected: -data, actual: items[0]); } int result = 0; var target = new ActionBlock <int>(i => { Assert.Equal(expected: 0, actual: result); result = i; Assert.Equal(expected: -data, actual: i); }); wob.LinkTo(target, new DataflowLinkOptions { PropagateCompletion = true }); await target.Completion; } // Test successful processing when no clone function exists { var data = new object(); var wob = new WriteOnceBlock <object>(null); Assert.True(wob.Post(data)); Assert.False(wob.Post(new object())); object result; for (int i = 0; i < 3; i++) { Assert.True(wob.TryReceive(out result)); Assert.Equal(expected: data, actual: result); Assert.Equal(expected: data, actual: wob.Receive()); Assert.Equal(expected: data, actual: await wob.ReceiveAsync()); IList <object> items; Assert.True(((IReceivableSourceBlock <object>)wob).TryReceiveAll(out items)); Assert.Equal(expected: 1, actual: items.Count); Assert.Equal(expected: data, actual: items[0]); } result = null; var target = new ActionBlock <object>(o => { Assert.Null(result); result = o; Assert.Equal(expected: data, actual: o); }); wob.LinkTo(target, new DataflowLinkOptions { PropagateCompletion = true }); await target.Completion; } }
public async Task TestReceiveThenPost() { var wob = new WriteOnceBlock<int>(null); var ignored = Task.Run(() => wob.Post(42)); Assert.Equal(expected: 42, actual: wob.Receive()); // this should always pass, but due to race we may not test what we're hoping to await wob.Completion; wob = new WriteOnceBlock<int>(null); Task<int> t = wob.ReceiveAsync(); Assert.False(t.IsCompleted); wob.Post(16); Assert.Equal(expected: 16, actual: await t); }
public async Task TestCloning() { // Test cloning when a clone function is provided { int data = 42; var wob = new WriteOnceBlock<int>(x => -x); Assert.True(wob.Post(data)); Assert.False(wob.Post(data + 1)); for (int i = 0; i < 3; i++) { int item; Assert.True(wob.TryReceive(out item)); Assert.Equal(expected: -data, actual: item); Assert.Equal(expected: -data, actual: wob.Receive()); Assert.Equal(expected: -data, actual: await wob.ReceiveAsync()); IList<int> items; Assert.True(((IReceivableSourceBlock<int>)wob).TryReceiveAll(out items)); Assert.Equal(expected: items.Count, actual: 1); Assert.Equal(expected: -data, actual: items[0]); } int result = 0; var target = new ActionBlock<int>(i => { Assert.Equal(expected: 0, actual: result); result = i; Assert.Equal(expected: -data, actual: i); }); wob.LinkTo(target, new DataflowLinkOptions { PropagateCompletion = true }); await target.Completion; } // Test successful processing when no clone function exists { var data = new object(); var wob = new WriteOnceBlock<object>(null); Assert.True(wob.Post(data)); Assert.False(wob.Post(new object())); object result; for (int i = 0; i < 3; i++) { Assert.True(wob.TryReceive(out result)); Assert.Equal(expected: data, actual: result); Assert.Equal(expected: data, actual: wob.Receive()); Assert.Equal(expected: data, actual: await wob.ReceiveAsync()); IList<object> items; Assert.True(((IReceivableSourceBlock<object>)wob).TryReceiveAll(out items)); Assert.Equal(expected: 1, actual: items.Count); Assert.Equal(expected: data, actual: items[0]); } result = null; var target = new ActionBlock<object>(o => { Assert.Null(result); result = o; Assert.Equal(expected: data, actual: o); }); wob.LinkTo(target, new DataflowLinkOptions { PropagateCompletion = true }); await target.Completion; } }
/// <summary> /// Connect to a target on first of bound proxies, or use ping based dynamic lookup /// </summary> /// <param name="address"></param> /// <param name="ct"></param> /// <returns></returns> public override async Task ConnectAsync(SocketAddress address, CancellationToken ct) { Info.Address = address; if (Info.Address.Family == AddressFamily.Bound) { // Unwrap proxy and connect address. If not bound, use local address to bind to. if (_boundEndpoint == null) { _boundEndpoint = address; // Unwrap bound address while (_boundEndpoint.Family == AddressFamily.Bound) { _boundEndpoint = ((BoundSocketAddress)_boundEndpoint).LocalAddress; } } Info.Address = ((BoundSocketAddress)Info.Address).RemoteAddress; } // // Get the named host from the registry if it exists - there should only be one... // This is the host we shall connect to. It can contain proxies to use as well. // var hostList = await Provider.NameService.LookupAsync( Info.Address.ToString(), NameRecordType.Host, ct).ConfigureAwait(false); Host = hostList.FirstOrDefault(); if (Host == null) { // If there is no host in the registry, create a fake host record for this address Host = new NameRecord(NameRecordType.Host, Info.Address.ToString()); } else { if (!Host.Name.Equals(Info.Address.ToString(), StringComparison.CurrentCultureIgnoreCase)) { // Translate the address to host address Info.Address = new ProxySocketAddress(Host.Name); } } // Commit all options that were set until now into info Info.Options.UnionWith(_optionCache.Select(p => Property <ulong> .Create( (uint)p.Key, p.Value))); // // Create tpl network for connect - prioritize input above errored attempts using // prioritized scheduling queue. // var retries = new CancellationTokenSource(); ct.Register(() => retries.Cancel()); var errors = new TransformBlock <DataflowMessage <INameRecord>, DataflowMessage <INameRecord> >( async(error) => { if (error.FaultCount > 0) { Host.RemoveReference(error.Arg.Address); await Provider.NameService.AddOrUpdateAsync(Host, retries.Token).ConfigureAwait(false); ProxyEventSource.Log.LinkFailure(this, error.Arg, Host, error.LastFault); } await Task.Delay((error.FaultCount + 1) * _throttleDelayMs, retries.Token).ConfigureAwait(false); return(error); }, new ExecutionDataflowBlockOptions { NameFormat = "Error (Connect) Id={1}", MaxDegreeOfParallelism = 2, // 2 parallel retries CancellationToken = retries.Token }); var linkAdapter = DataflowMessage <INameRecord> .CreateAdapter( new ExecutionDataflowBlockOptions { NameFormat = "Adapt (Connect) Id={1}", CancellationToken = ct, MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded, MaxMessagesPerTask = DataflowBlockOptions.Unbounded, SingleProducerConstrained = true, EnsureOrdered = false }); var linkQuery = Provider.NameService.Read( new ExecutionDataflowBlockOptions { NameFormat = "Query (Connect) Id={1}", CancellationToken = ct, EnsureOrdered = true }); var pinger = CreatePingBlock(errors, Info.Address, new ExecutionDataflowBlockOptions { NameFormat = "Ping (Connect) Id={1}", CancellationToken = ct, MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded, MaxMessagesPerTask = 1, EnsureOrdered = false }); var linker = CreateLinkBlock(errors, new ExecutionDataflowBlockOptions { NameFormat = "Link (Connect) Id={1}", CancellationToken = ct, MaxDegreeOfParallelism = 1, // Ensure one link is created at a time. MaxMessagesPerTask = DataflowBlockOptions.Unbounded, EnsureOrdered = false }); var connection = new WriteOnceBlock <IProxyLink>(l => l, new DataflowBlockOptions { NameFormat = "Final (Connect) Id={1}", MaxMessagesPerTask = 1, // Auto complete when link is created EnsureOrdered = false }); linkQuery.ConnectTo(linkAdapter); linkAdapter.ConnectTo(linker); errors.ConnectTo(pinger); pinger.ConnectTo(linker); linker.ConnectTo(connection); // // Now connect by starting the connection pipeline from query source... // if (_boundEndpoint != null) { // // User asked for specific set of proxies. Try linking with each // until we have a successful link. // await linkQuery.SendAsync(r => r.Matches(_boundEndpoint, NameRecordType.Proxy), ct).ConfigureAwait(false); } else { // // Consider all endpoints - if the host has a candidate list // use this list to directly link, and then ping remaining with // a throttle. Otherwise do a full ping. // var pingAdapter = DataflowMessage <INameRecord> .CreateAdapter( new ExecutionDataflowBlockOptions { NameFormat = "Any (Connect) Id={1}", CancellationToken = ct, MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded, MaxMessagesPerTask = DataflowBlockOptions.Unbounded, SingleProducerConstrained = true, EnsureOrdered = false }); var remaining = Provider.NameService.Read( new ExecutionDataflowBlockOptions { NameFormat = "Remaining (Connect) Id={1}", CancellationToken = ct, EnsureOrdered = true }); remaining.ConnectTo(pingAdapter); if (Host.References.Any()) { // Delay ping through errors path to give references time to link... pingAdapter.ConnectTo(errors); await linkQuery.SendAsync(r => r.Matches(Host.References, NameRecordType.Proxy), ct).ConfigureAwait(false); } else { // Send directly to ping pingAdapter.ConnectTo(pinger); } await remaining.SendAsync(r => r.IsProxyForHost(Info.Address), ct) .ConfigureAwait(false); } // Wait until a connected link is received. Then cancel the remainder of the pipeline. try { _link = await connection.ReceiveAsync(ct); connection.Complete(); retries.Cancel(); Host.AddReference(_link.Proxy.Address); Host.LastActivity = _link.Proxy.LastActivity = DateTime.Now; await Provider.NameService.AddOrUpdateAsync(_link.Proxy, ct).ConfigureAwait(false); } catch (Exception e) { throw SocketException.Create("Failed to connect", e); } finally { await Provider.NameService.AddOrUpdateAsync(Host, ct).ConfigureAwait(false); } }
public async Task TestPostThenReceive() { var wob = new WriteOnceBlock<int>(i => i); for (int i = 10; i < 15; i++) { bool posted = wob.Post(i); Assert.Equal(expected: i == 10, actual: posted); } int item; Assert.True(wob.TryReceive(out item)); Assert.Equal(expected: 10, actual: item); await wob.Completion; wob = new WriteOnceBlock<int>(null); wob.Post(42); Task<int> t = wob.ReceiveAsync(); Assert.True(t.IsCompleted); Assert.Equal(expected: 42, actual: t.Result); await wob.Completion; }
public void AsyncReceiveTest () { int result = -1; var mre = new ManualResetEventSlim (false); var block = new WriteOnceBlock<int> (null); block.ReceiveAsync ().ContinueWith (i => { result = i.Result; mre.Set (); }); Task.Factory.StartNew (() => { Thread.Sleep (100); block.Post (42); }); Assert.IsTrue (mre.Wait (1000)); Assert.AreEqual (42, result); }
public void AsyncReceiveTestCanceled () { var src = new CancellationTokenSource (); var block = new WriteOnceBlock<int> (null); var task = block.ReceiveAsync (src.Token); Task.Factory.StartNew (() => { Thread.Sleep (800); block.Post (42); }); Thread.Sleep (50); src.Cancel (); AggregateException ex = null; try { task.Wait (); } catch (AggregateException e) { ex = e; } Assert.IsNotNull (ex); Assert.IsNotNull (ex.InnerException); Assert.IsInstanceOfType (typeof(OperationCanceledException), ex.InnerException); Assert.IsTrue (task.IsCompleted); Assert.AreEqual (TaskStatus.Canceled, task.Status); }
public async Task TestWriteOnceBlock() { var writeOnceBlockTest = new WriteOnceBlock <int>(i => i); var queueBlockTest = new BufferBlock <string>(); var transformBlockTest = new TransformBlock <string, Tuple <int, string> >(async str => Tuple.Create(await writeOnceBlockTest.ReceiveAsync(), str)); var actionBlockTest = new ActionBlock <Tuple <int, string> >(tuple => Console.WriteLine($"I received int {tuple.Item1} and string {tuple.Item2}.")); queueBlockTest.LinkTo(transformBlockTest, new DataflowLinkOptions { PropagateCompletion = true }); transformBlockTest.LinkTo(actionBlockTest, new DataflowLinkOptions { PropagateCompletion = true }); writeOnceBlockTest.Post(3); queueBlockTest.Post("String1"); queueBlockTest.Post("String2"); writeOnceBlockTest.Post(4); writeOnceBlockTest.Post(5); queueBlockTest.Post("String3"); queueBlockTest.Post("String4"); queueBlockTest.Complete(); await actionBlockTest.Completion; }