我正在使用System.IO.File.Copy将文件从远程共享复制到本地系统。如果副本花费太长时间,我该如何实现超时?如何在使用File.Copy时实现超时?
1
A
回答
1
例如,它可以做到用这种方式async
- await
模式:
Task timeoutTask = Task.Delay(TimeSpan.FromSeconds(10));
// I use a completion source to set File.Copy thread from its own
// thread, and use it later to abort it if needed
TaskCompletionSource<Thread> copyThreadCompletionSource = new TaskCompletionSource<Thread>();
// This will await while any of both given tasks end.
await Task.WhenAny
(
timeoutTask,
Task.Factory.StartNew
(
() =>
{
// This will let main thread access this thread and force a Thread.Abort
// if the operation must be canceled due to a timeout
copyThreadCompletionSource.SetResult(Thread.CurrentThread);
File.Copy(@"C:\x.txt", @"C:\y.txt");
}
)
);
// Since timeoutTask was completed before wrapped File.Copy task you can
// consider that the operation timed out
if (timeoutTask.Status == TaskStatus.RanToCompletion)
{
// Timed out!
Thread copyThread = await copyThreadCompletionSource.Task;
copyThread.Abort();
}
你可能封装这一重新使用它,只要你想:
public static class Timeout
{
public static async Task<bool> ForAsync(Action operationWithTimeout, TimeSpan maxTime)
{
Contract.Requires(operationWithTimeout != null);
Task timeoutTask = Task.Delay(maxTime);
TaskCompletionSource<Thread> copyThreadCompletionSource = new TaskCompletionSource<Thread>();
// This will await while any of both given tasks end.
await Task.WhenAny
(
timeoutTask,
Task.Factory.StartNew
(
() =>
{
// This will let main thread access this thread and force a Thread.Abort
// if the operation must be canceled due to a timeout
copyThreadCompletionSource.SetResult(Thread.CurrentThread);
operationWithTimeout();
}
)
);
// Since timeoutTask was completed before wrapped File.Copy task you can
// consider that the operation timed out
if (timeoutTask.Status == TaskStatus.RanToCompletion)
{
// Timed out!
Thread copyThread = await copyThreadCompletionSource.Task;
copyThread.Abort();
return false;
}
else
{
return true;
}
}
}
某处项目你可以这样称呼上述方法:
bool success = await Timeout.ForAsync(() => File.Copy(...), TimeSpan.FromSeconds(10));
if(success)
{
// Do stuff if File.Copy didn't time out!
}
注意我已经使用Thread.Abort()
而不是使用CancellationToken
。在你的用例中,你需要调用一个你不能使用所谓的取消模式的同步方法,我相信这可能是Thread.Abort()
可能是有效选项的少数情况之一。
在一天结束时,如果出现超时,代码将中止执行File.Copy
的线程,因此,它应该足以停止I/O操作。
0
你可以实现一个简单的方法类似于下面的东西,建立在Stream.CopyToAsync()其接受取消标记:
static async Task Copy(string destFilePath, string sourceFilePath, int timeoutSecs)
{
var cancellationSource = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSecs));
using (var dest = File.Create(destFilePath))
using (var src = File.OpenRead(sourceFilePath))
{
await src.CopyToAsync(dest, 81920, cancellationSource.Token);
}
}
正如你所看到的,它可以创建一个CancellationTokenSource()其指定后自动取消本身时间。
try
{
await Copy(@"c:\temp\test2.bin", @"c:\temp\test.bin", 60);
Console.WriteLine("finished..");
}
catch (OperationCanceledException ex)
{
Console.WriteLine("cancelled..");
}
catch (Exception ex)
{
Console.WriteLine("error..");
}
或旧的方式:
var copyInProgress = Copy(@"c:\temp\test2.bin", @"c:\temp\test.bin", 60);
copyInProgress.ContinueWith(
_ => { Console.WriteLine("cancelled.."); },
TaskContinuationOptions.OnlyOnCanceled
);
copyInProgress.ContinueWith(
_ => { Console.WriteLine("finished.."); },
TaskContinuationOptions.OnlyOnRanToCompletion
);
copyInProgress.ContinueWith(
_ => { Console.WriteLine("failed.."); },
TaskContinuationOptions.OnlyOnFaulted
);
copyInProgress.Wait();
这是很容易改进上述代码,以使用一个第二消除令牌可被控制
可以使用异步使用复制方法由用户(通过取消按钮)。所有你需要使用的是CancellationTokenSource.CreateLinkedTokenSource
相关问题
- 1. fcntl.flock - 如何实现超时?
- 2. 如何实现epoll超时?
- 3. 如何在使用sync.WaitGroup.wait时实现超时?
- 4. 如何用Quartz实现超时?
- 5. 如何在python中实现超时?
- 6. 在c中实现超时#
- 7. 在QT中实现超时
- 8. 在HTTP中实现超时
- 9. 在webviews中实现超时
- 10. 使用ScheduledExecutorService实现不活动超时
- 11. 如何实现套接字超时?
- 12. 如何实现getline()的超时?
- 13. 如何在此流上不支持超时时实现.NET Stream超时
- 14. 如何在使用SQLiteOpenHelper时实现SQLCipher
- 15. 如何在不支持时使用超时实现javascript同步xmlhttprequest?
- 16. 如何使用django实现实时?
- 17. 如何在超时时段实现Get-Credential
- 18. 如何实现会话超时页面使用asp.net mvc的
- 19. 如何使用pimefaces实现会话超时处理?
- 20. 如何使用boost :: asio :: read_some实现超时?
- 21. 实现一般的超时
- 22. 实现超时功能/块
- 23. 实现通信超时
- 24. 套接字超时实现
- 25. 使用Delphi读取文件时实现超时
- 26. Excel VBA:如何实现定时器来检查代码超时
- 27. 在软件中实现超时
- 28. 在Z3中实现数组超时
- 29. 在TFTP中的C超时实现
- 30. 在Python中实现超时扭曲
也许比超时更好的是异步工作:[异步文件复制/移动在C#](http://stackoverflow.com/questions/882686/asynchronous-file-copy-move- in-c-sharp) –
https://msdn.microsoft.com/zh-cn/magazine/cc163851.aspx –