首页 文章

为什么我的WebClient上传文件代码挂起?

提问于
浏览
1

我正在使用VSTS 2008 C#.Net 3.5 ASP.Net IIS 7.0在客户端开发Windows窗体应用程序来上传文件,在服务器端我使用aspx文件接收此文件 .

我发现单击按钮触发上传事件后,我的客户端应用程序将挂起 . 任何想法有什么不对,怎么解决?谢谢!

客户端代码,

public partial class Form1 : Form
    {
        private static WebClient client = new WebClient();
        private static ManualResetEvent uploadLock = new ManualResetEvent(false);

        private static void Upload()
        {
            try
            {
                Uri uri = new Uri("http://localhost/Default2.aspx");
                String filename = @"C:\Test\1.dat";

                client.Headers.Add("UserAgent", "TestAgent");
                client.UploadProgressChanged += new UploadProgressChangedEventHandler(UploadProgressCallback);
                client.UploadFileCompleted += new UploadFileCompletedEventHandler(UploadFileCompleteCallback);
                client.UploadFileAsync(uri, "POST", filename);
                uploadLock.WaitOne();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace.ToString());
            }
        }

        public static void UploadFileCompleteCallback(object sender, UploadFileCompletedEventArgs e)
        {
            Console.WriteLine("Completed! ");
            uploadLock.Set();
        }

        private static void UploadProgressCallback(object sender, UploadProgressChangedEventArgs e)
        {
            Console.WriteLine("{0}    uploaded {1} of {2} bytes. {3} % complete...",
                (string)e.UserState,
                e.BytesSent,
                e.TotalBytesToSend,
                e.ProgressPercentage);

            // Console.WriteLine (e.ProgressPercentage);
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Upload();
        }
    }

服务器端代码:

protected void Page_Load(object sender, EventArgs e)
    {
        string agent = HttpContext.Current.Request.Headers["UserAgent"];
        using (FileStream file = new FileStream(@"C:\Test\Agent.txt", FileMode.Append, FileAccess.Write))
        {
            byte[] buf = Encoding.UTF8.GetBytes(agent);
            file.Write(buf, 0, buf.Length);
        }

        foreach (string f in Request.Files.AllKeys)
        {
            HttpPostedFile file = Request.Files[f];
            file.SaveAs("C:\\Test\\UploadFile.dat");
        }
    }

1 回答

  • 4

    您正在主Windows事件线程中等待,因此您的GUI将被冻结 .

    试试这个(使用非静态方法允许你使用Control.Invoke方法在windows GUI线程上运行回调并释放这个线程以便重绘)

    public partial class Form1 : Form
    {
        private static WebClient client = new WebClient();
        private static ManualResetEvent uploadLock = new ManualResetEvent(false);
    
        private void Upload()
        {
            try
            {
                Cursor=Cursors.Wait;
                Uri uri = new Uri("http://localhost/Default2.aspx");
                String filename = @"C:\Test\1.dat";
    
                client.Headers.Add("UserAgent", "TestAgent");
                client.UploadProgressChanged += new UploadProgressChangedEventHandler(UploadProgressCallback);
                client.UploadFileCompleted += new UploadFileCompletedEventHandler(UploadFileCompleteCallback);
                 client.UploadFileAsync(uri, "POST", filename);    
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace.ToString());
                this.Cursor=Cursors.Default;
                this.Enabled=false;
            }
        }
    
        public void UploadFileCompleteCallback(object sender, UploadFileCompletedEventArgs e)
        {
          // this callback will be invoked by the async upload handler on a ThreadPool thread, so we cannot touch anything GUI-related. For this we have to switch to the GUI thread using control.BeginInvoke
          if(this.InvokeRequired)
          {
               // so this is called in the main GUI thread
               this.BeginInvoke(new UploadFileCompletedEventHandler(UploadFileCompleteCallback); // beginInvoke frees up the threadpool thread faster. Invoke would wait for completion of the callback before returning.
          }
          else
          {
              Cursor=Cursors.Default;
              this.enabled=true;
              MessageBox.Show(this,"Upload done","Done");
          }
    public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                Upload();
            }
        }
    }
    

    并在您的进度中执行相同的操作(例如,您可以更新进度条指示器) .

    干杯,弗洛里安

相关问题