所以这里我有一个功能
static Task<bool> LoginAsync(SignupData sd)
{
return Task.Run<bool>(()=>Login(sd));
}
还有另一项功能
async
现在,我遇到了这种模式的一个相当不同的实现,您可以将Task<TResult>
关键字添加到返回async Task<TResult> LoginAsync(SignupData sd)
的函数中(这样它最终看起来像: TResult
)。在这种情况下,即使您返回Task<TResult>
而不是static Task<bool> LoginAsync(SignupData sd)
{
return Task.Run<bool>(()=>Login(sd));
}
,该程序仍会编译。
我的问题是,应该优先考虑哪种实施方式?
async static Task<bool> LoginAsync(SignupData sd)
{
bool success=Login(sd);
return success;
}
或者这个?
public class LoginSteps {
private final LoginPage login;
SharedDriver driver;
public LoginSteps(LoginPage login, SharedDriver driver) {
this.login=login;
this.driver=driver;
}
@Given("^the Pctice Login page is loaded$")
public void the_Poactice_Login_is_loaded ()throws Throwable {
driver.getDriver().get("....ogin/");
}
@When("^The logins into the account$")
public void the_logins_into_the_account() throws Throwable {
login.login(false);
}
答案 0 :(得分:7)
你不应该这样做。如果异步方法可以阻止线程被阻塞,则它们非常有用。在你的情况下,你的方法没有避免这种情况,它总是阻塞一个线程。
如何处理长阻塞调用取决于应用程序。对于UI应用程序,您希望使用Task.Run
来确保不阻止UI线程。对于例如网络应用程序,你不想要使用Task.Run
,你只想使用你已经拥有的线程来防止在一个人满足的情况下使用两个线程。
您的异步方法无法可靠地知道什么最适合调用者,因此不应该通过其API表明它最了解。您应该只使用同步方法并让调用者决定。
那就是说,我建议寻找一种方法来创建一个真正异步的LoginAsync
实现。例如,如果它从数据库加载数据,请使用OpenAsync
打开连接,使用ExecuteReaderAsync
检索数据。如果它连接到Web服务,请使用异步方法连接您正在使用的任何协议。如果它以其他方式登录,请执行您需要的任何操作 异步。
如果您采用这种方法,async
和await
关键字非常有意义,可以很容易地创建这样的实现。
答案 1 :(得分:0)
虽然HVD是正确的,但我会潜入异步,试图描述其预期用途。
async关键字和随附的await关键字是在应用程序中实现非阻塞代码模式的快捷方法。虽然它与任务并行库(TPL)的其余部分完美配合,但通常使用它并不完全相同。它的优点在于编译器在异步性中编织的优雅,并且允许在不明确地分离单独的线程的情况下处理它,这可能是你想要的也可能不是。
例如,让我们看一些代码:
async static Task<bool> DoStuffAsync()
{
var otherAsyncResult = doOtherStuffAsync();
return await otherAsyncResult
}
请参阅await关键字?它说,返回呼叫者,继续,直到我们得到你需要的结果。不要阻止,不要使用新线程,但基本上在准备就绪时返回结果(A任务)。然后调用代码可以继续进行,而不用担心结果,直到我们拥有它为止。
通常这最终会要求您的代码在整个过程中变为非阻塞状态(一直异步),这通常是一个难以理解的过渡。但是,如果可以,它就非常强大。
处理代码的更好方法是使同步代码调用异步代码,然后等待它。这样你就会尽可能地保持异步。最好在应用程序中尽可能高地强制该级别,如果可能的话,一直到UI。
希望有道理。 TPL是一个很大的主题,Async / Await确实添加了一些有趣的构造代码的方法。 https://msdn.microsoft.com/en-us/library/hh191443.aspx