4 Replies - 282 Views - Last Post: 29 January 2014 - 09:59 AM Rate Topic: -----

#1 prabh  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 3
  • View blog
  • Posts: 381
  • Joined: 27-December 08

raising events

Posted 28 January 2014 - 09:35 PM

Hello guys,
using System;
using System.IO;
using System.Net;
using System.Threading;
using System.Web;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

namespace YoTube_Downloader
{
    public class MyEventArgs : EventArgs
    {
        private readonly long _bytesRead;
        private readonly long _fileSize;

        public MyEventArgs(long bytesRead,long fileSize)
        {
            _bytesRead = bytesRead;
            _fileSize = fileSize;
        }

        public long BytesRead
        {
            get { return _bytesRead; }
        }

        public long FileSize
        {
            get { return _fileSize; }
        }
    }
    class Downloader
    {        
        public event EventHandler<MyEventArgs> DownloadProgressEvent;
        public event EventHandler Download_Completed;

        HttpWebRequest webRequest;
        HttpWebResponse webResponse;
        Stream strResponse;
        FileStream strLocal;

        string dFileName;
        string dDownloadLink;
        Thread thrDownload;

        public Downloader(string filename, string downloadlink)
        {
            this.dFileName = filename;
            this.dDownloadLink = downloadlink;
        }
        public void Start()
        {
            thrDownload = new Thread(Download);
            thrDownload.Start();
        }
        private void Download()
        {
            DownloadProgressChanged d;
            using (WebClient wcDownload = new WebClient())
            {
                try
                {                    
                    // Create a request to the file we are downloading
                    webRequest = (HttpWebRequest)WebRequest.Create(dDownloadLink);
                    // Set default authentication for retrieving the file
                    webRequest.Credentials = CredentialCache.DefaultCredentials;
                    // Retrieve the response from the server
                    webResponse = (HttpWebResponse)webRequest.GetResponse();
                    // Ask the server for the file size and store it
                    Int64 fileSize = webResponse.ContentLength;
                    string fileType = webResponse.ResponseUri.ToString();
                    // Open the URL for download
                    strResponse = wcDownload.OpenRead(fileType);
                    // Create a new file stream where we will be saving the data (local drive)
                    strLocal = new FileStream(dFileName, FileMode.Create, FileAccess.Write, FileShare.None);

                    // It will store the current number of bytes we retrieved from the server
                    int bytesSize = 0;

                    byte[] downBuffer = new byte[2048];
                    
                    // Loop through the buffer until the buffer is empty
                    while ((bytesSize = strResponse.Read(downBuffer, 0, downBuffer.Length)) > 0)
                    {
                        // Write the data from the buffer to the local hard drive
                        strLocal.Write(downBuffer, 0, bytesSize);
                        this.DownloadProgressEvent.Invoke(this, new MyEventArgs(strLocal.Length, fileSize));
                    }
                }
                finally
                {
                    this.Download_Completed.Invoke(this, new EventArgs());
                    strResponse.Close();
                    strLocal.Close();                   
                }
            }
        }

    }
}



But when I call this class from my form and do this
void load_Video_Info(string video_id)
        {
            pDownloader = new Downloader(txtOutDir.Text + "temp.dat", link);
            pDownloader.DownloadProgressEvent += new EventHandler<MyEventArgs>(pDownloader_DownloadProgressEvent);
            pDownloader.Download_Completed += new EventHandler(pDownloader_Download_Completed);
            pDownloader.Start();
        
        }
 void pDownloader_DownloadProgressEvent(object sender, MyEventArgs e)
        {
            lblStatus.Text = e.BytesRead.ToString();
        }




I get this

Quote

Cross-thread operation not valid: Control 'lblStatus' accessed from a thread other than the thread it was created on.

This post has been edited by prabh: 28 January 2014 - 09:36 PM


Is This A Good Question/Topic? 0
  • +

Replies To: raising events

#2 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3452
  • View blog
  • Posts: 10,654
  • Joined: 05-May 12

Re: raising events

Posted 28 January 2014 - 10:29 PM

The error is pretty self explanatory. You are trying to change the UI from a thread that is not same thread that the UI was created in. Read about how to make thread-safe calls to Windows Form controls.
Was This Post Helpful? 0
  • +
  • -

#3 prabh  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 3
  • View blog
  • Posts: 381
  • Joined: 27-December 08

Re: raising events

Posted 28 January 2014 - 11:44 PM

Thanks for your reply but this is not what I want.
I don't want to directly update any control like lables.

Quote

I want to send Updated value to my form whenever DownloadProgressEvent is invoked.


Like we do it using WebClient
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);


I know it can be done using delegates to send MyEventArgs, but I don't know how.

This post has been edited by prabh: 28 January 2014 - 11:47 PM

Was This Post Helpful? 0
  • +
  • -

#4 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3452
  • View blog
  • Posts: 10,654
  • Joined: 05-May 12

Re: raising events

Posted 29 January 2014 - 09:40 AM

But the code you posted is updating a label:
 void pDownloader_DownloadProgressEvent(object sender, MyEventArgs e)
        {
            lblStatus.Text = e.BytesRead.ToString();
        }



If you didn't want to update a label, then don't update a label.
Was This Post Helpful? 2
  • +
  • -

#5 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3452
  • View blog
  • Posts: 10,654
  • Joined: 05-May 12

Re: raising events

Posted 29 January 2014 - 09:59 AM

Basically, the issue is due to your line of code here:
this.DownloadProgressEvent.Invoke(this, new MyEventArgs(strLocal.Length, fileSize));



The Invoke() call there didn't buy you anything because all you did was bypass the C# compiler. The code:
DownloadProgressEvent(this, new MyEventArgs(strLocal.Length, fileSize));


ends up generating this code:
this.DownloadProgressEvent.Invoke(this, new MyEventArgs(strLocal.Length, fileSize));



You are calling the Delegate.Invoke() when the link I referred to above is referring to using Control.Invoke().
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1