如何在 c# 中实际编写/结束异步方法
本文关键字:结束 异步方法 | 更新日期: 2023-09-27 18:13:02
我知道我需要在async
标记的方法中等待事物以使其异步,但我不知道如何实际结束它造成的漏洞。
static async void Example()
{
int t = await getIntAsync();
WriteLine($"computer: {t}");
}
由于getIntAsync被标记为异步,因此我必须在该方法中等待,否则会收到警告。但是哦,不,在我在getIntAsync中等待的方法中,我必须将其标记为aasync,然后除非那里有等待,否则我会收到警告。依此类推,似乎无穷大。我怎样才能让它停止?
我有几个人告诉我把
await Task.Delay(1000);
在我的代码中,但我知道答案不能像在所有生产代码中延迟一秒那样臭。
其他几个人说了一个任务方法来结束它,例如
static Task task()
{
//code
}
但是,除非我标记async
否则它会引发同样的警告,让我陷入这种混乱。 我知道
static Task task()
{
//code
return Task.FromResult(0);
}
从技术上讲,它可以工作,但同样,这似乎太过代码气味,无法在整个生产中出现。
我只是不明白...
编辑:因为它是被要求。我知道这是一种非常微不足道的方法,但它也只是我用来练习的方法。
static async Task<int> getIntAsync()
{
Console.Write("Enter the number: ");
int n = int.Parse(Console.ReadLine());
return n;
}
这里令人困惑的是,你并没有真正做一些异步的事情。 Console.ReadLine()
是一种同步方法。简单地在某处键入async
或await
并不能神奇地使其异步。
由于此代码仅用于测试和学习,因此使其异步的一种方法是使用 Task.Run()
将其放在另一个线程上(对于生产代码中的许多情况,我不建议这样做(:
static Task<int> getIntAsync()
{
Console.Write("Enter the number: ");
return Task.Run(() => int.Parse(Console.ReadLine());
}
这里不需要async
关键字,因为您没有等待某些东西。您只需返回一个Task<int>
,该在用户输入值并解析该值时完成。
然后,您的Example()
方法的工作方式是这样的:
static async void Example()
{
int t = await getIntAsync();
WriteLine($"computer: {t}");
}
命中await
时,控制流将返回到调用方,此方法的其余部分(对t
的分配和对Console.WriteLine()
的调用(被调度为在getIntAsync()
返回的Task<int>
完成时执行的延续。
需要以下内容(async 关键字是必需的,await 也是必需的,这只是最佳实践(:
- 异步关键字
- 等待关键字
- 您希望在异步进程运行时独立工作的某些进程。
- 通常,返回的值来自您的 await 任务(它应该填充结束孔(。
下面是使用 StreamReader 的示例,
async Task<string> GetStringFromReaderAsync()
{
Streamreader sr = new StreamReader("filename.txt");
Task<string> getStringTask = sr.ReadLineAsync("filepath");
//Allow user to continue with some other work.
DoFileLookup();
string result = await sr.getStringTask();
return result.ToString();
}
更多信息:https://msdn.microsoft.com/en-us/library/system.io.streamreader.readlineasync(v=vs.110(.aspx
更多关于 Async 和 Await: https://msdn.microsoft.com/en-us/library/mt674882.aspx
static async Task<int> getIntAsync() { Console.Write("Enter the number: "); int n = int.Parse(Console.ReadLine()); return n; }
这将同步运行,因为没有 await 语句,也没有对异步方法的等待调用
一般的想法是这样的
public async Task<int> ExecuteAsync() //Method return type is Task<int>
{
// Error: return type is not int. Return type is Task<int>
return db.SaveChangesAsync();
// OK: returns a task handle that you can await on in you code that called ExecuteAsync()
// you thread continues processing in your calling function until you try to read the value from this return statement.
return await db.SaveChangesAsync();
// Ok. Your Thread leaves here and returns when result available.
// no further Processing done in calling function
return db.SaveChangesAsync().Result;
// Ok. This is not required in this case,
// but if you have an async method that has multiple return points,
// and one of them does not depend on an async method, you can wrap
// the output e.g. return await Task.FromResult(0);
return await Task.FromResult(db.SaveChangesAsync().Result);
return 0; //also ok.
}
添加到下面的另一个答案。
static async Task<int> GetIntAsync()
{
Console.Write("Enter the number: ");
return await Task.Run(() => int.Parse("1"));
}
这种方法使同步运行的内容包装在任务中。但是,您永远不应该这样做(除非您当然知道自己在做什么(,因为这会生成另一个线程。我使用它的一个用例是在网络服务器中卸载,但除此之外,这通常是一个坏主意。因此,虽然您可能一开始的意图是最大限度地利用单个线程,但现在您最终得到了两个线程的工作。