Ale*_*lex 2 c# multithreading asynchronous
我有以下方法:
public void PutFile(string ID, Stream content)
{
try
{
ThreadPool.QueueUserWorkItem(o => putFileWorker(ID, content));
}
catch (Exception ex)
{
OnPutFileError(this, new ExceptionEventArgs { Exception = ex });
}
}
Run Code Online (Sandbox Code Playgroud)
putFileWorker方法如下所示:
private void putFileWorker(string ID, Stream content)
{
//Get bucket name:
var bucketName = getBucketName(ID)
.ToLower();
//get file key
var fileKey = getFileKey(ID);
try
{
//if the bucket doesn't exist, create it
if (!Amazon.S3.Util.AmazonS3Util.DoesS3BucketExist(bucketName, s3client))
s3client.PutBucket(new PutBucketRequest { BucketName = bucketName, BucketRegion = S3Region.EU });
PutObjectRequest request = new PutObjectRequest();
request.WithBucketName(bucketName)
.WithKey(fileKey)
.WithInputStream(content);
S3Response response = s3client.PutObject(request);
var xx = response.Headers;
OnPutFileCompleted(this, new ValueEventArgs { Value = ID });
}
catch (Exception e)
{
OnPutFileError(this, new ExceptionEventArgs { Exception = e });
}
}
Run Code Online (Sandbox Code Playgroud)
我已经创建了一个小控制台应用程序来测试它.我为OnPutFileError和OnPutFileCompleted事件连接了事件处理程序.
如果我调用我的PutFile方法,并进入此步骤,它将进入"//如果存储桶不存在,创建它"行,然后退出.没有例外,没有错误,没有.它没有完成(我也在我的事件处理程序上设置了断点) - 它只是退出.
如果我在没有ThreadPool.QueueUserWorkItem的情况下运行相同的方法,那么它运行良好...
我错过了什么吗?
ThreadPool线程是后台线程(请参阅链接).如果主线程退出,它们将不会保持应用程序运行.
通常,在WinForms应用程序中,这不是问题,因为主UI线程调用Application.Run并开始处理事件.对于您的控制台应用程序,如果您的Main方法不等待工作项以某种方式完成,主线程将排队工作项然后退出.
您可以自己创建后台线程并将其IsBackground属性设置为false.或者你可以创建一个线程并调用Thread.Join来等待它完成.
- 编辑 -
如下面的注释所示,您还可以使用ManualResetEvent,甚至是Linik建议的自定义同步类.目标是阻塞主线程,直到后台线程完成.
要使用ManualResetEvent,请在主线程中创建它并将其作为参数传递.(为简洁起见,我将此处分配给静态变量.)
ManualResetEvent s_WaitEvent;
ManualResetEvent s_WaitEvent = new ManualResetEvent(false); // non-signaled
// queue work item here
s_WaitEvent.WaitOne();
Run Code Online (Sandbox Code Playgroud)
在工作线程结束时,发出事件信号:
s_WaitEvent.Set();
Run Code Online (Sandbox Code Playgroud)
Link的CountDownLatch很好,如果你有许多线程必须处理才能退出.您还可以为每个线程使用单独的ManualResetEvent,并使用WaitHandle.WaitAll(WaitHandle [])等待它们全部完成.(ManualResetEvent继承自WaitHandle.)
| 归档时间: |
|
| 查看次数: |
2641 次 |
| 最近记录: |