gpt4 book ai didi

同样具有匿名回调处理程序的 C# 异步方法无法正确流动

转载 作者:行者123 更新时间:2023-11-30 15:00:04 25 4
gpt4 key购买 nike

下面是 C# async 方法的代码,它也有两个 WebClient 控件事件的回调处理程序:DownloadProgressChanged>打开读取完成。当我运行代码时,它最初流向“await DownloadStringTaskAsync()”调用并退出。然后我看到 DownloadProgressChanged 的匿名事件处理程序代码被触发,这就是我遇到问题的地方。然后代码流向“return strRet”语句,因此该方法的返回值是分配给方法顶部的 strRet 的初始化值“(none)”,而不是在 OpenReadCompleted 匿名回调中分配给 strRet 的网页内容。

所以我需要等待 OpenReadCompleted 回调在控制流到返回语句之前执行,但我不确定如何正确执行此操作。如何更正代码,使其在 OpenReadCompleted 回调执行之前不会到达“return strRet”语句?

    /// <summary>
/// This method downloads the contents of a URL to a string. Returns the URL contents
/// as a string if it succeeds, throws an Exception if not.
/// <param name="strUrl">The URL to download.</param>
/// <param name="progress">An IProgress object to report download progress to. May be NULL.</param>
/// <param name="cancelToken">A cancellation token. May be NULL.</param>
/// <param name="iNumSecondsToWait">The number of seconds to wait before cancelling the download. Default is 30 seconds</param>
/// </summary>
/// <remarks>
/// Use "await" with this method wrapped in Task.run() to manage the process asynchronously.
///
/// NOTE: The DownloadProgressChanged() event is raised on the UI
/// thread so it is safe to do UI updates from the IProgress.Report()
/// method.
/// </remarks>
async public static Task<string> URLToString(string strUrl, IProgress<int> progress, CancellationToken cancelToken, int iNumSecondsToWait = 30)
{
// The string to be returned.
string strRet = "(none)";

strUrl = strUrl.Trim();

if (String.IsNullOrWhiteSpace(strUrl))
throw new ArgumentException("(Misc::URLToString) The URL is empty.");

if (iNumSecondsToWait < 1)
throw new ArgumentException("(Misc::URLToString) The number of seconds to wait is less than 1.");

// Asynchronous download. Note, the Silverlight version of WebClient does *not* implement
// IDisposable.
WebClient wc = new WebClient();

// Create a download progress changed handler so we can pass on progress
// reports to the caller if they provided a progress report object.
// This event is raised on the UI thread.
wc.DownloadProgressChanged += (s, e) =>
{
// Do we have a progress report handler?
if (progress != null)
// Yes, call it.
progress.Report(e.ProgressPercentage);

// If we have a cancellation token and the operation was cancelled, then abort the download.
if (cancelToken != null)
cancelToken.ThrowIfCancellationRequested();

}; // wc.DownloadProgressChanged += (s, e) =>

// Use a Lambda expression for the "completed" handler
// that writes the downloaded contents as a string to a file.
wc.OpenReadCompleted += (s, e) =>
{
// If we have a cancellation token and the operation was cancelled, then abort the download.
if (cancelToken != null)
cancelToken.ThrowIfCancellationRequested();

// Return the downloaded file as a string.
strRet = e.Result.ToString();
}; // wc.OpenReadCompleted += (s, e) =>

// Now make the call to download the file and do an asynchronous wait for the result.
await wc.DownloadStringTaskAsync(new Uri(strUrl));

// wc.DownloadStringAsync(new Uri(strUrl));

return strRet;
} // async public static void URLToStr

================================

更新:根据我收到的答案,我已将代码修改为以下内容:

    async public static Task<string> URLToStringAsync(string strUrl, IProgress<int> progress, CancellationToken cancelToken, int iNumSecondsToWait = 30)
{
strUrl = strUrl.Trim();

if (String.IsNullOrWhiteSpace(strUrl))
throw new ArgumentException("(Misc::URLToStringAsync) The URL is empty.");

if (iNumSecondsToWait < 1)
throw new ArgumentException("(Misc::URLToStringAsync) The number of seconds to wait is less than 1.");

// Asynchronous download. Note, the Silverlight version of WebClient does *not* implement
// IDisposable.
WebClient wc = new WebClient();

// Create a download progress changed handler so we can pass on progress
// reports to the caller if they provided a progress report object.
// This event is raised on the UI thread.
wc.DownloadProgressChanged += (s, e) =>
{
// Do we have a progress report handler?
if (progress != null)
// Yes, call it.
progress.Report(e.ProgressPercentage);

// If we have a cancellation token and the operation was cancelled, then abort the download.
if (safeCancellationCheck(cancelToken))
wc.CancelAsync();
}; // wc.DownloadProgressChanged += (s, e) =>

// Now make the call to download the file and do an asynchronous wait for the result.
return await wc.DownloadStringTaskAsync(new Uri(strUrl));
} // async public static void URLToStringAsync

最佳答案

我发现了几个问题:

a) 从 MSDN 文档看来 DownloadStringTaskAsync 不会触发 DownloadProgressChanged

b) OpenReadCompleted仅当您使用 OpenReadAsync 创建请求时才会触发事件。不会为 DownloadStringTaskAsync 触发它。

c) 您可以使用 DownloadStringCompleted事件来获取 DownloadStringTaskAsync 的结果,但是为什么如果您使用的是异步/等待,您可以这样做:

strRet = await wc.DownloadStringTaskAsync(new Uri(strUrl));

关于同样具有匿名回调处理程序的 C# 异步方法无法正确流动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15854792/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com