我有看起來像這樣的同步方法:TAP - 使用內部EAP-方法來減少代碼
public void DownloadPackages()
{
long received = 0;
double total = PackageConfigurations.Select(config => SizeHelper.GetRemoteFileSize(config.UpdatePackageUri))
.Where(updatePackageSize => updatePackageSize != null)
.Sum(updatePackageSize => updatePackageSize.Value);
if (!Directory.Exists(_applicationUpdateDirectory))
Directory.CreateDirectory(_applicationUpdateDirectory);
foreach (var updateConfiguration in PackageConfigurations)
{
WebResponse webResponse = null;
try
{
var webRequest = WebRequest.Create(updateConfiguration.UpdatePackageUri);
using (webResponse = webRequest.GetResponse())
{
var buffer = new byte[1024];
_packageFilePaths.Add(new UpdateVersion(updateConfiguration.LiteralVersion),
Path.Combine(_applicationUpdateDirectory,
$"{updateConfiguration.LiteralVersion}.zip"));
using (FileStream fileStream = File.Create(Path.Combine(_applicationUpdateDirectory,
$"{updateConfiguration.LiteralVersion}.zip")))
{
using (Stream input = webResponse.GetResponseStream())
{
if (input == null)
throw new Exception("The response stream couldn't be read.");
int size = input.Read(buffer, 0, buffer.Length);
while (size > 0)
{
if (_downloadCancellationTokenSource.IsCancellationRequested)
{
fileStream.Flush();
fileStream.Close();
throw new OperationCanceledException(_downloadCancellationTokenSource.Token);
}
fileStream.Write(buffer, 0, buffer.Length);
received += size;
OnUpdateDownloadProgressChanged(received,
(long)total, (float)(received/total) * 100);
size = input.Read(buffer, 0, buffer.Length);
}
}
}
}
}
finally
{
webResponse?.Close();
}
}
}
嗯,我已經實現了EAP。這意味着,我已經寫了包裝在一個任務此方法並引發事件的方法:
public void DownloadPackagesAsync()
{
_downloadCancellationTokenSource.Dispose();
_downloadCancellationTokenSource = new CancellationTokenSource();
Task.Factory.StartNew(DownloadPackages).ContinueWith(DownloadTaskCompleted,
_downloadCancellationTokenSource.Token,
TaskContinuationOptions.None,
TaskScheduler.Default);
}
private void DownloadTaskCompleted(Task task)
{
if (task.IsCanceled)
return;
var exception = task.Exception;
if (exception != null)
OnUpdateDownloadFailed(exception.InnerException ?? exception);
else
OnUpdateDownloadFinished(this, EventArgs.Empty);
}
第一個問題:是不是正確的同步方式更新進度或者是有另一種方式?
第二個問題:有,在我的班級管理CancellationTokenSource
的私人領域,我提供,看起來像這樣的方法:
public void CancelDownload()
{
_downloadCancellationTokenSource.Cancel();
}
當正在調用該方法,在下載被取消。但是,當我使用TAP時,這也是正確的嗎?
現在,第三個問題涉及使用TAP的異步方法。 它應該是public async Task DownloadPackagesTaskAsync(IProgress<UpdateDownloadProgressChangedEventArgs> progress)
。實際上,我需要複製整個代碼並對其進行調整,但是這會給我帶來很多冗餘線路,我想。我想過在內部使用EAP方法。問題是我沒有任何返回類型,並且連續不能使用TaskCompletionSource
以便使用它。我的方向是在.NET框架中的代碼:http://referencesource.microsoft.com/#System/net/System/Net/webclient.cs,d250a06fb9c3ac77,references
有沒有什麼辦法可以實現這個目標?
使用'StartNew'編寫假異步方法[是反模式](http://blogs.msdn.com/b/pfxteam/archive/2012/03/24/10287244.aspx)。如果你的工作是異步的,那麼API應該是異步的。如果您需要爲反向編譯原因支持同步API,請使用[在我的關於brownfield async的文章中描述的布爾標誌參數hack(https://msdn.microsoft.com/zh-cn/magazine/mt238404.aspx))。 –