C# WaitHandle.WaitAny();WaitHandle.WaitAll()用法问题
我的应用程序未正确退出。我只是想打印连接总数,然后等待所有上传操作完成,然后优雅地退出 下面是代码C# WaitHandle.WaitAny();WaitHandle.WaitAll()用法问题,c#,multithreading,waithandle,C#,Multithreading,Waithandle,我的应用程序未正确退出。我只是想打印连接总数,然后等待所有上传操作完成,然后优雅地退出 下面是代码 using System; using System.Net; using System.Threading; using System.IO; using System.Text; namespace ServicePointDemo { class Program { struct UploadState { publi
using System;
using System.Net;
using System.Threading;
using System.IO;
using System.Text;
namespace ServicePointDemo
{
class Program
{
struct UploadState
{
public string Filename;
public AutoResetEvent are;
}
static void Main(string[] args)
{
AutoResetEvent are = new AutoResetEvent(false);
ServicePoint sp = ServicePointManager.FindServicePoint(new Uri("ftp://xxx.xxx.xxx.xxx/public"));
UploadState us1 = new UploadState();
us1.are = new AutoResetEvent(false);
us1.Filename = @"C:\inventory.xls";
UploadState us2 = new UploadState();
us2.are = new AutoResetEvent(false);
us2.Filename = @"C:\somefile.txt";
Thread t1, t2;
t1 = new Thread(new ParameterizedThreadStart(DoUpload));
t2 = new Thread(new ParameterizedThreadStart(DoUpload));
t1.Start(us1);
t2.Start(us2);
Console.WriteLine("Waiting for something to trigger up");
WaitHandle.WaitAny(new WaitHandle[] { us1.are, us2.are });
Console.WriteLine("CurrentConnections = {0}", sp.CurrentConnections);
Console.WriteLine("Waiting for all operations to complete...");
WaitHandle.WaitAll(new WaitHandle[] { us1.are, us2.are });
Console.WriteLine("Press enter to quit");
Console.ReadLine();
}
static void DoUpload(object state)
{
string filename = ((UploadState)state).Filename;
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create("ftp://172.16.130.22/public/" + Path.GetFileName(filename));
Console.WriteLine("Upload URI = {0}", ftpRequest.RequestUri.AbsoluteUri);
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
ftpRequest.Credentials = new NetworkCredential("anonymous", "guest@");
ftpRequest.Proxy = new WebProxy();
Stream stream = null;
FileStream file = new FileStream(filename, FileMode.Open);
Console.WriteLine("Total file size of {0} = {1}", filename, file.Length);
StreamReader rdr = new StreamReader(file);
Console.WriteLine("Getting bytes of {0}", filename);
byte[] fileBytes = Encoding.ASCII.GetBytes(rdr.ReadToEnd());
rdr.Close();
Console.WriteLine("Acquiring connection of {0} upload...", filename);
try
{
stream = ftpRequest.GetRequestStream();
Console.WriteLine("Upload of {0} has acquired a connection", filename);
((UploadState)state).are.Set();
stream.Write(fileBytes, 0, fileBytes.Length);
Console.WriteLine("Uploading {0} complete", filename);
}
catch (Exception ex)
{
Console.WriteLine("Exception has occurred: {0}", ex.Message);
}
finally
{
Console.WriteLine("Ending uploading {0}", filename);
stream.Close();
((UploadState)state).are.Set();
}
Console.WriteLine("Quit DoUpload() for {0}", filename);//...is not executed(?)
}
}
}
你的自动回复事件似乎有种族问题 如果线程运行得很快,它们可以在主线程到达第一个WaitAny()之前两次调用自动重置事件上的Set()。这将允许它传递第一个WaitAny(),但会阻塞WaitAll(),因为两个线程都不再调用Set()。(您可以在启动两个后台线程之后,在主线程中放置一个长线程.Sleep()来模拟此情况) 我建议您使用两个单独的AutoResetEvents(或仅普通设置),一个是在获取连接时设置的(),另一个是在连接完成时设置的,因此您不需要依赖线程的计时。在每个线程上用对Join()的调用替换WaitAll()调用 顺便说一下,您不需要Main()中的第一个AutoResetEvent
are
,因为它没有被使用