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

时间:2009-10-09 10:11:53

标签: c# asp.net .net visual-studio-2008 webclient

我正在使用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 个答案:

答案 0 :(得分: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();
        }
    }
}

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

干杯, 弗洛里安