首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WaitHandle.WaitAny()和WaitHandle.WaitAll()使用问题

WaitHandle.WaitAny()和WaitHandle.WaitAll()使用问题
EN

Stack Overflow用户
提问于 2009-11-10 19:30:53
回答 2查看 3.8K关注 0票数 0

我的应用程序没有正确退出。我只是尝试打印连接的总数,然后等待所有上传操作完成,然后优雅地退出。

下面是代码..。

代码语言:javascript
复制
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(?)
        }
    }
}
EN

回答 2

Stack Overflow用户

发布于 2009-11-10 20:15:12

您的AutoResetEvents上似乎存在竞争条件

如果线程运行得很快,它们可以在主线程到达第一个WaitAny()之前对自动重置事件调用Set()两次。这将允许它传递第一个WaitAny(),但会在WaitAll()上阻塞,因为两个线程都不再调用Set()。(您可以通过在启动两个后台线程后立即在主线程中放置一个长Thread.Sleep()来模拟此过程)

我建议您使用两个单独的AutoResetEvents (或者只是普通的EventWaitHandles),一个是在获取连接时设置的,另一个是在连接完成时设置的,所以您不需要依赖线程的时间。

票数 0
EN

Stack Overflow用户

发布于 2009-11-11 00:13:37

将WaitAll()调用替换为对每个线程的Join()调用。

顺便说一下,您不需要在AutoResetEvent ()中使用第一个Main are,因为它并没有被使用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1707306

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档