我有以下方法:
public int getData() { return 2; } // suppose it is slow and takes 20 sec // pseudocode public int GetPreviousData() { Taskt = new Task (() => getData()); return _cachedData; // some previous value _cachedData = t.Result; // _cachedData == 2 }
我不想等待已经运行的操作的结果.
我希望_cachedData
在Task
完成后返回并更新它.
这该怎么做?我正在使用.net framework 4.5.2
您可能想在out
此处使用参数:
public TaskGetPreviousDataAsync(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 TaskGetPreviousDataAsync(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); } }