c# - 从列表中查找未完成任务的详细信息
问题描述
我有一个递归下降函数,它将父目录中的所有文件和任意数量的子目录中的所有文件发送到 AWS S3。根据这篇文章,我有 5 分钟的超时时间,设置为让文件夹中的所有文件都被推送到 S3,如果需要的时间更长,我想取消任何剩余的任务。当我为令牌设置取消标志时,无论是否Delay
超时,我都希望能够从列表中获取所有未完成的任务并提取请求的详细信息以进行日志Wait
记录WhenAny
. 微软表示,任务的Id和CurrentId不能被认为是唯一的。
如何从任务对象中获取创建任务的请求对象?
private static void ProcessDirectory(System.IO.DirectoryInfo di)
{
int _timeOut = 5 * 60 * 1000;
foreach (var item in di.GetDirectories())
{
ProcessDirectory(item);
}
using (Amazon.S3.AmazonS3Client _client = new Amazon.S3.AmazonS3Client())
{
System.Threading.CancellationTokenSource _cancellationTokenSource = new System.Threading.CancellationTokenSource();
System.Collections.Generic.List<System.Threading.Tasks.Task<Amazon.S3.Model.PutObjectResponse>> _responses = new List<System.Threading.Tasks.Task<Amazon.S3.Model.PutObjectResponse>>(1000);
foreach (var item in di.GetFiles())
{
_responses.Add(_client.PutObjectAsync(new Amazon.S3.Model.PutObjectRequest
{
BucketName = SiteSettings.Bucket,
CannedACL = Amazon.S3.S3CannedACL.PublicRead,
FilePath = item.FullName,
Key = item.FullName.Replace(SiteSettings.OutputRoot, string.Empty).Replace(@"\", "/")
}, _cancellationTokenSource.Token));
}
// Wait 5 Mins + 1 sec
System.Threading.Tasks.Task.WhenAny(System.Threading.Tasks.Task<Amazon.S3.Model.PutObjectResponse>.WhenAll(_responses)
, System.Threading.Tasks.Task.Delay(_timeOut)).Wait(_timeOut + 1000);
_cancellationTokenSource.Cancel(); //Cancel the remaining pushes for this folder.
foreach (var item in _responses)
{
if (!item.IsCompleted)
{
//Pull the key value to log
}
}
}
}
解决方案
创建每个工作项后,您可以为每个工作项保存一些唯一密钥,然后使用该密钥进行日志记录。在此示例中,我用作item.FullName
键。此外,为了更好的可读性,我还冒昧地在类型之前删除了长名称空间,希望您不会介意:
private static void ProcessDirectory(System.IO.DirectoryInfo di)
{
int _timeOut = 5 * 60 * 1000;
foreach (var item in di.GetDirectories())
{
ProcessDirectory(item);
}
using (Amazon.S3.AmazonS3Client _client = new Amazon.S3.AmazonS3Client())
{
CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
Dictionary<string, Task<Amazon.S3.Model.PutObjectResponse>> _responses =
new Dictionary<string, Task<Amazon.S3.Model.PutObjectResponse>>(1000);
foreach (var item in di.GetFiles())
{
// use any unique information about your item here
var itemName = item.FullName;
_responses[itemName] = _client.PutObjectAsync(new Amazon.S3.Model.PutObjectRequest
{
BucketName = SiteSettings.Bucket,
CannedACL = Amazon.S3.S3CannedACL.PublicRead,
FilePath = itemName,
Key = item.FullName.Replace(SiteSettings.OutputRoot, string.Empty).Replace(@"\", "/")
}, _cancellationTokenSource.Token);
}
// Wait 5 Mins + 1 sec
Task.WhenAny(Task<Amazon.S3.Model.PutObjectResponse>.WhenAll(_responses.Values)
,Task.Delay(_timeOut)).Wait(_timeOut + 1000);
_cancellationTokenSource.Cancel(); //Cancel the remaining pushes for this folder.
foreach (var item in _responses)
{
if (!item.Value.IsCompleted)
{
//Pull the key value to log
var keyValue = item.Key;
}
}
}
}
List<Task<Amazon.S3.Model.PutObjectResponse>>
你看,我用where key交换Dictionary<string, Task<Amazon.S3.Model.PutObjectResponse>>
了文件的全名。因此,如果字典中的某些任务未在 5 分钟内完成,您将能够获取未加载的文件的名称。
希望能帮助到你。
推荐阅读
- react-native - React Native Flatlist 不重新渲染
- glsl - 如何在 GLSL 中复制数组?
- oauth-2.0 - 如何在我自己的 oauth2 客户端中注销
- javascript - 如何使用 jQuery 从输入中删除选中的属性
- html - 我如何从下一个 img 标签设置 div 高度?
- java - 如何以 Struts 2 所需的形式上传文件
- c++ - qt 做昂贵的操作会破坏样式表
- dji-sdk - DJI Onboardsdk 无法自动起飞
- sql - 用于进行数字比较的转换/过滤字符串
- git - Git 连接被 Git 克隆拒绝。如何使用正确的凭据重新连接