如何使我的方法可等待?

45

我该如何编写自己的异步可等待方法?

我发现在某些情况下编写异步方法非常容易:

private async Task TestGeo()
{
    Geolocator geo = new Geolocator();
    Geoposition pos = await geo.GetGeopositionAsync();
    double dLat = pos.Coordinate.Latitude;
    double dLong = pos.Coordinate.Latitude;
}

但是遗憾的是,并不是所有的方法都可以随意变为异步方式,比如这种情况行不通:

private async Task TestAsyncAwait()
{
    int i = await TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5);
}

...它停止了,给我一个编译错误:“无法等待int”;设计时的提示也类似地告诉我,“类型'int'不可等待”

我尝试过同样的方法,但结果相同:

    Task<int> i = await TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5);

我该做什么才能使我的方法可等待?

更新

正如Linebacker和S. Cleary所指出的那样(与曾经在KNBR上的那只猫有关系吗?),这个方法可以工作:

int i = await Task.Run(() => TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5));

也就是说,它会进行编译,但从不"移动"

在运行时,它告诉我应该"等待"对TestAsyncAwait()的调用,但如果我这样做的话,它根本无法编译...


4
int i = await Task.Run(() => TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5)); - L.B
1
我建议您阅读TAP - Christian
那么Lambda现在不仅是时尚的,而且是必须的吗?至少到目前为止,我认为它们是聪明的技巧。 - B. Clay Shannon-B. Crow Raven
你确定你想让这个可等待吗? - Stephen Cleary
不,我只是在尝试 - 我想知道如何使方法可等待,这样当我需要时,我就可以“一直做下去”或“甚至不用(太多)思考”。 - B. Clay Shannon-B. Crow Raven
4个回答

28
你只需要返回一个可等待对象。常见的选择是 Task/Task<TResult>;可以使用 Task.Run(在后台线程上执行代码)或 TaskCompletionSource<T>(包装一个异步事件)创建 Task
阅读基于任务的异步模式以获取更多信息。

18

你的方法

private async Task TestAsyncAwait()
{
    int i = await TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5);
}

应该像这样编写

private async Task TestAsyncAwait()
{
    Task<int> t = new Task<int>(() =>
    {
        return TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5);
    });
    t.Start();
    await t;
}

如果您需要返回int类型,请将Task类型替换为int:

private async Task<int> TestAsyncAwait()
{
    Task<int> t = new Task<int>(() =>
    {
        return TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5);
    });
    t.Start();
    return await t;
}

链接已失效。 - Denis G. Labrecque

3
var something = Task<int>.Factory.StartNew(() => 0);
something.Wait();
int number = something.Result;

2
因为原帖明显是在尝试异步执行,所以被踩了。 - aaronburro
4
感谢aaronburro添加了一个踩的解释。这种情况太少见了。 - philologon
罕见而有用。 - Marcelo Scofano Diniz

1

您需要消耗等待的返回或者返回Task<await调用的类型>

  1. private async Task<Geoposition> TestGeo()
    {
        Geolocator geo = new Geolocator();
        return await geo.GetGeopositionAsync();
    }
    
  2. private async Task<int> TestAsyncAwait()
    {
        return await TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5);
    }
    
这段代码是与IT相关的。

问题是关于#2的,对于#2,错误显示为"Type 'int' is not awaitable"。 - Jeson Martajaya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接