public TestFlow SendConversationUpdate() { return(new TestFlow( async() => { // NOTE: we need to .Wait() on the original Task to properly observe any exceptions that might have occurred // and to have them propagate correctly up through the chain to whomever is waiting on the parent task // The following StackOverflow answer provides some more details on why you want to do this: // https://stackoverflow.com/questions/11904821/proper-way-to-use-continuewith-for-tasks/11906865#11906865 // // From the Docs: // https://docs.microsoft.com/dotnet/standard/parallel-programming/exception-handling-task-parallel-library // Exceptions are propagated when you use one of the static or instance Task.Wait or Wait // methods, and you handle them by enclosing the call in a try/catch statement. If a task is the // parent of attached child tasks, or if you are waiting on multiple tasks, multiple exceptions // could be thrown. await this._testTask.ConfigureAwait(false); var cu = Activity.CreateConversationUpdateActivity(); cu.MembersAdded.Add(this._adapter.Conversation.User); await _adapter.ProcessActivityAsync((Activity)cu, _callback, default(CancellationToken)).ConfigureAwait(false); }, this)); }
/// <summary> /// Adds an activity from the user to the bot. /// </summary> /// <param name="userActivity">The activity to send.</param> /// <returns>A new <see cref="TestFlow"/> object that appends a new activity from the user to the modeled exchange.</returns> /// <remarks>This method does not modify the original <see cref="TestFlow"/> object.</remarks> public TestFlow Send(IActivity userActivity) { if (userActivity == null) { throw new ArgumentNullException("You have to pass an Activity"); } return(new TestFlow( _testTask.ContinueWith((task) => { // NOTE: See details code in above method. task.Wait(); return _adapter.ProcessActivityAsync((Activity)userActivity, _callback, default(CancellationToken)); }).Unwrap(), this)); }