Skip to main content
 首页 » 编程设计

c#之为什么我的 WebClient 上传文件代码挂起

2024年02月24日31bhlsheji

我正在使用 VSTS 2008 + C# + .Net 3.5 + ASP.Net + IIS 7.0 在客户端开发一个 Windows Forms 应用程序来上传文件,在服务器端我使用 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"); 
        } 
    } 

请您参考如下方法:

您正在主窗口事件线程中等待,因此您的 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(); 
        } 
    } 
} 

并在您的进度中做同样的事情(例如,您可以更新进度条指示器)。

干杯, 弗洛里安