"C# in a Nutshell"의 비동기 함수 섹션을 읽었습니다. 예를 들면 다음과 같습니다 :캐시 비동기 함수 결과가 C#
'다운로드'버튼 클릭 이벤트를 처리해야한다고 가정하고 다운로드 결과를 캐싱하려고합니다. 웹 사이트를 다운로드하는 데 신경 쓰지 않으면 버튼을 반복해서 클릭하면 eaiser가 표시됩니다.
private static Dictionary<string, string> _cache = new Dictionary<string, string>();
async Task<string> DownloadAsync(string uri)
{
string content;
if (_cache.TryGetValue(uri, out content)) return content;
return _cache[uri] = await new WebClient().DownloadStringTaskAsync(uri);
}
하지만 예를 들어 두 번 연속 클릭하면 동일한 웹 사이트로 중복 다운로드가 실행됩니다. 이를 보호하기 위해이 책에서는 Task<string>
캐싱을 제안합니다.
private static Dictionary<string, Task<string>> _futureCache = new Dictionary<string, Task<string>>();
Task<string> GetWebPage(string uri)
{
lock (_futureCache)
{
Task<string> task;
if (_futureCache.TryGetValue(uri, out task)) return task;
return _futureCache[uri] = new WebClient().DownloadStringTaskAsync(uri);
}
}
그러나이 보호 기능이 어떻게 효과적 일 수 있는지 이해하지 못합니다. 내가 클릭 이벤트 처리기는이 같은 것입니다 가정
_downloadBtn.Click += async (sender, args) =>
{
var uri = "http://www.bbc.co.uk"; // for argument sake, it always downloads bbc...
string result = await GetWebPage(uri);
// process the result...
};
어떤 이유로, 첫 번째 클릭에 의해 트리거 다운로드가 진행 여전히 후 버튼이 2 시간 동안 클릭, 경우; 아직 두 번째 클릭이 시작될 때까지 캐시가 첫 번째 다운로드에서 채워지지 않았으므로 페이지를 두 번 다운로드하지 않습니까? 내 이해가 잘못 되었다면 그 이유를 설명하십시오. 그렇지 않으면 반복되는 사용자 클릭을 방지하는 캐시를 구현하는 방법은 무엇입니까?
그렇다면 캐시가 이벤트 핸들러 (UI) 컨텍스트 외부에서 사용되는 경우 효과적으로 작동한다는 것을 알고 있습니다. 그 아래에 한 번만 다운로드됩니다.
async void Foo()
{
var uri = "http://www.bbc.co.uk";
string result;
for (int i = 0; i < 2; i++) //Stimulate repeated call
{
result = await GetWebPage(uri);
Console.WriteLine(result.Length);
}
}
코드가 정상적으로 작동합니다. 힌트 :'GetWebPage'에는'await'이 없습니다 :) –
@LucasTrzesniewski 그것은 의도적으로 동시성을 유발할 것을 기다리지 않고 있습니다! – stt106
바로 코드가 이미 진행중인 작업 (또는 해당 문제에 대해 이미 완료된 상태) 인 경우 두 번째 작업을 추가하지 않습니다 :) –