当前位置:  开发笔记 > 编程语言 > 正文

如何从Task返回结果?

如何解决《如何从Task返回结果?》经验,为你挑选了1个好方法。

我有以下方法:

public int getData() { return 2; } // suppose it is slow and takes 20 sec

// pseudocode
public int GetPreviousData()
{
    Task t = new Task(() => getData());
    return _cachedData; // some previous value
    _cachedData = t.Result; // _cachedData == 2
}

我不想等待已经运行的操作的结果.

我希望_cachedDataTask完成后返回并更新它.

这该怎么做?我正在使用.net framework 4.5.2



1> Matías Fidem..:

您可能想在out此处使用参数:

public Task GetPreviousDataAsync(out int cachedData)
{
    Task t = Task.Run(() => getData());
    cachedData = _cachedData; // some previous value
    return t; // _cachedData == 2
}

int cachedData;
cachedData = await GetPreviousDataAsync(out int cachedData);

注意Task.Run事项:这会启动一个使用线程池的任务并返回一个Task让调用者决定是否应该等待,继续或触发并忘记它.

请参阅以下示例.我已将所有内容重新安排到课堂上:

class A
{
    private int _cachedData;
    private readonly static AutoResetEvent _getDataResetEvent = new AutoResetEvent(true);

    private int GetData()
    {
        return 1;
    }

    public Task GetPreviousDataAsync(out int cachedData)
    {
        // This will force calls to this method to be executed one by one, avoiding
        // N calls to his method update _cachedData class field in an unpredictable way
        // It will try to get a lock in 6 seconds. If it goes beyong 6 seconds it means that 
        // the task is taking too much time. This will prevent a deadlock
        if (!_getDataResetEvent.WaitOne(TimeSpan.FromSeconds(6)))
        {
            throw new InvalidOperationException("Some previous operation is taking too much time");
        }

        // It has acquired an exclusive lock since WaitOne returned true

        Task getDataTask = Task.Run(() => GetData());
        cachedData = _cachedData; // some previous value

        // Once the getDataTask has finished, this will set the 
        // _cachedData class field. Since it's an asynchronous 
        // continuation, the return statement will be hit before the
        // task ends, letting the caller await for the asynchronous
        // operation, while the method was able to output 
        // previous _cachedData using the "out" parameter.
        getDataTask.ContinueWith
        (
            t =>
            {
                if (t.IsCompleted)
                    _cachedData = t.Result;

                // Open the door again to let other calls proceed
                _getDataResetEvent.Set();
            }
        );

        return getDataTask;
    }

    public void DoStuff()
    {
        int previousCachedData;
        // Don't await it, when the underlying task ends, sets
        // _cachedData already. This is like saying "fire and forget it"
        GetPreviousDataAsync(out previousCachedData);
    }
}

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有