почему мой код загрузки файла WebClient зависает? - PullRequest
1 голос
/ 09 октября 2009

Я использую 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");
        }
    }

1 Ответ

4 голосов
/ 09 октября 2009

вы ожидаете в потоке событий главного окна, поэтому ваш графический интерфейс будет заморожен.

Попробуйте это (использование нестатических методов позволяет использовать метод Control.Invoke для запуска обратных вызовов в потоке графического интерфейса Windows и освободить этот поток для перерисовки)

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();
        }
    }
}

И проделайте то же самое в своем прогрессе (например, вы можете обновить индикатор выполнения).

Ура, Florian

...