2

我正在测试我的 WPF 应用程序连接到 Azure Blob 存储以使用 TPL(任务)下载一堆图像。预计在 Live 环境中,在已部署的位置将存在与 Internet 的高度瞬态连接。

我在 BlobRequestOptions 中设置了重试策略和超时,如下所示:

//Note the values here are for test purposes only
//CloudRetryPolicy is a custom method returning adequate Retry Policy
// i.e. retry 3 times, wait 2 seconds between retries
blobClient.RetryPolicy = CloudRetryPolicy(3, new TimeSpan(0, 0, 2));

BlobRequestOptions bro = new BlobRequestOptions() { Timeout = TimeSpan.FromSeconds(20) };
blob.DownloadToFile(LocalPath, bro);

上述语句在按预期工作的后台任务中,并且我在后台任务和继续任务中进行了适当的异常处理。

为了测试异常处理和我的恢复代码,我通过拔出网线来模拟互联网断开连接。我已经在 UI 线程上将一个方法连接到 System.Net.NetworkChange.NetworkAvailabilityChanged 事件,我可以按预期检测连接/断开连接并相应地更新 UI。

我的问题是:如果我在下载文件时(通过 blob.DownloadToFile)拉网线,后台线程就会挂起。它不会超时,不会崩溃,不会抛出异常,什么都没有!!!在我写的时候,我一直在等待大约 30 分钟,并且没有发生与后台任务相关的响应/处理。

如果我拉网线,在下载开始之前,执行如预期。即我可以看到发生重试、引发异常并提前传递等等。

有没有人经历过类似的行为?有什么技巧/建议可以克服这种行为/问题吗?

顺便说一句,我知道我可以在检测到网络连接丢失时取消下载任务,但我不想这样做,因为网络连接可以在超时时间内恢复,并且下载过程可以从它的位置继续被打断了。我已经测试了这种自动恢复并且运行良好。

下面是我的代码结构的粗略指示(语法不正确,只是一个流程指示)

btnClick()
{
  declare background_task
  attach continuewith_task to background task
  start background task
}

background_task()
{
  try
  {
    ... connection setup ... 
    blob.DownloadToFile(LocalPath, bro);
  }
  catch(exception ex)
  {
     ... exception handling ....
     // in case of connectivity loss while download is in progress
     // this block is not getting executed
     // debugger just sits idle without a current statement
  }
}

continuewith_task()
{
  check if antecedent task is faulted
  {
     ... do recovery work ...
     // this is working as expected if connectivity is lost
     // before download starts
     // this task does not get called if connectivity is lost
     // while file transfer is taking place
  }
  else
  {
     .. further processing ...
  }
}
4

2 回答 2

2

我相信 Avkash 是正确的。另外,需要明确的是,您基本上永远不会看到网络删除错误,因此对其进行测试没有多大意义。您将看到大量连接被拒绝、冲突、资源丢失、只读帐户、限制、访问被拒绝,甚至 DNS 解析失败,具体取决于您处理存储帐户的方式。你应该测试那些。

话虽如此,我建议您根本不要将 RetryPolicy 与 blob 或表存储一起使用。对于您实际遇到的大多数错误,它们一开始是不可重试的(例如 404、409、403 等)。当你有一个重试策略时,默认情况下它会在接下来的 2 分钟内再试 4 次。例如,重试错误的凭据是没有意义的。

您最好自己简单地处理错误并有选择地重试(超时和油门是这里唯一有意义的事情)。

于 2012-10-09T17:05:52.493 回答
1

您的问题主要是因为 Azure 存储客户端库在下面使用文件流类,以及为什么 API 挂起与 Windows Azure Blob 客户端库没有直接关系。直接通过网络调用文件流 API,当突然移除网络电缆时,您可以看到完全相同的行为,但是优雅地移除网络将返回不同的行为。

如果您在 Internet 上搜索,您会发现流媒体类不会检测到网络丢失,这就是为什么在您的代码中您可以检查网络断开事件,然后停止后台流媒体线程。

于 2012-10-09T16:35:28.123 回答