-
-
Notifications
You must be signed in to change notification settings - Fork 8.7k
[dotnet] allow asynchronous command execution #13952
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
36b49d8
3f30c8d
1197b0f
173447c
2472a8a
ab31f5f
103f8d5
7101abe
49741eb
0c8c691
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| // <copyright file="AsyncHelper.cs" company="WebDriver Committers"> | ||
| // Licensed to the Software Freedom Conservancy (SFC) under one | ||
| // or more contributor license agreements. See the NOTICE file | ||
| // distributed with this work for additional information | ||
| // regarding copyright ownership. The SFC licenses this file | ||
| // to you under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
| // </copyright> | ||
|
|
||
| using System; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace OpenQA.Selenium.Internal | ||
| { | ||
| /// <summary> | ||
| /// Encapsulates methods for working with asynchronous tasks. | ||
| /// </summary> | ||
| public static class AsyncHelper | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We either need to duplicate the helper class in both webdriver and support packages or make it public in webdriver to access it from support. This approach appears to be what other classes in the repo do.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duplicate, it is not a criminal.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, in this case I'm following what appears to be done elsewhere |
||
| { | ||
| private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None, | ||
| TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also wandering should we deny attaching children tasks via |
||
|
|
||
| public static TResult RunSync<TResult>(Func<Task<TResult>> func) | ||
| { | ||
| return _myTaskFactory.StartNew(() => | ||
| { | ||
| return func(); | ||
| }).Unwrap().GetAwaiter().GetResult(); | ||
| } | ||
|
|
||
| public static void RunSync(Func<Task> func) | ||
| { | ||
| _myTaskFactory.StartNew(() => | ||
| { | ||
| return func(); | ||
| }).Unwrap().GetAwaiter().GetResult(); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -158,6 +158,16 @@ public bool TryAddCommand(string commandName, CommandInfo info) | |||||
| /// <param name="commandToExecute">The command you wish to execute</param> | ||||||
| /// <returns>A response from the browser</returns> | ||||||
| public virtual Response Execute(Command commandToExecute) | ||||||
| { | ||||||
| return AsyncHelper.RunSync(() => this.ExecuteAsync(commandToExecute)); | ||||||
| } | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// Executes a command Asynchronously | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| /// </summary> | ||||||
| /// <param name="commandToExecute">The command you wish to execute</param> | ||||||
| /// <returns>A task object representing the asynchronous operation</returns> | ||||||
| public virtual async Task<Response> ExecuteAsync(Command commandToExecute) | ||||||
| { | ||||||
| if (commandToExecute == null) | ||||||
| { | ||||||
|
|
@@ -184,7 +194,7 @@ public virtual Response Execute(Command commandToExecute) | |||||
| HttpResponseInfo responseInfo = null; | ||||||
| try | ||||||
| { | ||||||
| responseInfo = Task.Run(async () => await this.MakeHttpRequest(requestInfo)).GetAwaiter().GetResult(); | ||||||
| responseInfo = await this.MakeHttpRequest(requestInfo); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it also makes sense to rename existing method |
||||||
| } | ||||||
| catch (HttpRequestException ex) | ||||||
| { | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,7 @@ | |
| using System.Collections.Generic; | ||
| using System.Collections.ObjectModel; | ||
| using System.Globalization; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace OpenQA.Selenium | ||
| { | ||
|
|
@@ -556,7 +557,25 @@ internal ReadOnlyCollection<IWebElement> GetElementsFromResponse(Response respon | |
| /// <returns>WebDriver Response</returns> | ||
| internal Response InternalExecute(string driverCommandToExecute, Dictionary<string, object> parameters) | ||
| { | ||
| return this.Execute(driverCommandToExecute, parameters); | ||
| return AsyncHelper.RunSync(() => this.InternalExecuteAsync(driverCommandToExecute, parameters)); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Executes commands with the driver asynchronously | ||
| /// </summary> | ||
| /// <param name="driverCommandToExecute">Command that needs executing</param> | ||
| /// <param name="parameters">Parameters needed for the command</param> | ||
| /// <returns>A task object representing the asynchronous operation</returns> | ||
| internal Task<Response> InternalExecuteAsync(string driverCommandToExecute, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I got the idea of
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure why it's there. If we change it, it should be part of a different PR, though. |
||
| Dictionary<string, object> parameters) | ||
| { | ||
| return this.ExecuteAsync(driverCommandToExecute, parameters); | ||
| } | ||
|
|
||
| internal Response Execute(string driverCommandToExecute, | ||
| Dictionary<string, object> parameters) | ||
| { | ||
| return AsyncHelper.RunSync(() => this.ExecuteAsync(driverCommandToExecute, parameters)); | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -565,15 +584,15 @@ internal Response InternalExecute(string driverCommandToExecute, Dictionary<stri | |
| /// <param name="driverCommandToExecute">A <see cref="DriverCommand"/> value representing the command to execute.</param> | ||
| /// <param name="parameters">A <see cref="Dictionary{K, V}"/> containing the names and values of the parameters of the command.</param> | ||
| /// <returns>A <see cref="Response"/> containing information about the success or failure of the command and any data returned by the command.</returns> | ||
| protected virtual Response Execute(string driverCommandToExecute, Dictionary<string, object> parameters) | ||
| protected virtual async Task<Response> ExecuteAsync(string driverCommandToExecute, Dictionary<string, object> parameters) | ||
| { | ||
| Command commandToExecute = new Command(this.sessionId, driverCommandToExecute, parameters); | ||
|
|
||
| Response commandResponse; | ||
|
|
||
| try | ||
| { | ||
| commandResponse = this.executor.Execute(commandToExecute); | ||
| commandResponse = await this.executor.ExecuteAsync(commandToExecute); | ||
| } | ||
| catch (System.Net.Http.HttpRequestException e) | ||
| { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The capital letter fix. Additionally, I would recommend to end all sentences in XML docs (
<summary>,<param>, etc.) with a period.