I have this code below
public void DownloadFile(string payloadFile)
{
new Thread(() =>
{
using (WebClient wc = new WebClient())
{
// code removed for brevity
// How to I pass payloadFile parameter to two event handler below?
wc.DownloadProgressChanged += HandleDownloadProgress;
wc.DownloadFileCompleted += HandleDownloadComplete;
wc.DownloadFileAsync(uri, _downloadPath + payloadFile);
}
}).Start();
}
public void HandleDownloadComplete(object sender, AsyncCompletedEventArgs args)
{
// I need to get payloadFile parameter here
}
public void HandleDownloadProgress(object sender, DownloadProgressChangedEventArgs args)
{
// I need to get payloadFile parameter here
}
How to I pass payloadFile parameter to two event handler above?
Pass payloadFile as userToken parameter:
wc.DownloadFileAsync(uri, _downloadPath + payloadFile, payloadFile);
After that you can get it from args:
public void HandleDownloadComplete(object sender, AsyncCompletedEventArgs args)
{
string payloadFile = (string)args.UserState;
}
public void HandleDownloadProgress(object sender, DownloadProgressChangedEventArgs args)
{
string payloadFile = (string)args.UserState;
}
Related
I am stuck and asking for your help, trying to make a software that check a txt file which is this format with CRC information and download the files inside that txt. These is just an example with same hash but in reality have different name, hash and size.
[FOLDER/FILE] [HASH] [FILESIZE]
./file1.dat f926038f 54
./Folder/file2.dat f926038f 54
./Folder/Subfolder/file3.dat f926038f 54
after I generate this type of information, I use this code to read where is the file...
private static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
StreamReader streamReader = new StreamReader(new WebClient().OpenRead(Import.ServerURL + Import.PatchlistName));
while (!streamReader.EndOfStream)
ListProcessor.AddFile(streamReader.ReadLine());
}
and these code to check the list of that file and write them in current folder
internal class ListProcessor
{
public static void AddFile(string File) => Import.Files.Add(new Import.File()
{
Name = File.Split(' ')[0],
Hash = File.Split(' ')[1],
Size = Convert.ToInt64(File.Split(' ')[2])
});
}
the problem is that files outside of any folders or subfolders they are downloading perfectly, but inside any folder or subfolder the download does not work.
PS: This is the order from where it starts:
Main.cs
private void Btn_Run_Click(object sender, EventArgs e)
{
if (!this.Btn_Run.Enabled)
return;
ListDownloader.DownloadList();
}
ListDownloader.cs
internal class ListDownloader
{
public static void DownloadList()
{
Common.ChangeStatus("LISTDOWNLOAD");
Common.DisableStart();
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(ListDownloader.backgroundWorker_DoWork);
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ListDownloader.backgroundWorker_RunWorkerCompleted);
if (backgroundWorker.IsBusy)
{
int num = (int) MessageBox.Show(Texts.GetText("UNKNOWNERROR", (object) "DownloadList isBusy"));
Application.Exit();
}
else
backgroundWorker.RunWorkerAsync();
}
private static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
StreamReader streamReader = new StreamReader(new WebClient().OpenRead(Import.ServerURL + Import.PatchlistName));
while (!streamReader.EndOfStream)
ListProcessor.AddFile(streamReader.ReadLine());
}
private static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
FileChecker.CheckFiles();
}
}
FileChecker.cs
internal class FileChecker
{
private static BackgroundWorker backgroundWorker = new BackgroundWorker();
public static void CheckFiles()
{
FileChecker.backgroundWorker.WorkerReportsProgress = true;
FileChecker.backgroundWorker.DoWork += new DoWorkEventHandler(FileChecker.backgroundWorker_DoWork);
FileChecker.backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(FileChecker.backgroundWorker_ProgressChanged);
FileChecker.backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(FileChecker.backgroundWorker_RunWorkerCompleted);
if (FileChecker.backgroundWorker.IsBusy)
{
int num = (int) MessageBox.Show(Texts.GetText("UNKNOWNERROR", (object) "CheckFiles isBusy"));
Application.Exit();
}
else
FileChecker.backgroundWorker.RunWorkerAsync();
}
private static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
foreach (Import.File file in Import.Files)
{
Import.fullSize += file.Size;
FileChecker.backgroundWorker.ReportProgress(0, (object) Path.GetFileName(file.Name));
if (!System.IO.File.Exists(file.Name) || string.Compare(Common.GetHash(file.Name), file.Hash) != 0)
{
Import.OldFiles.Add(file.Name);
}
else
{
Import.completeSize += file.Size;
FileChecker.backgroundWorker.ReportProgress(1);
}
}
}
private static void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage == 0)
{
Common.ChangeStatus("CHECKFILE", e.UserState.ToString());
}
else
{
Common.UpdateCompleteProgress(Computer.Compute(Import.completeSize));
Common.UpdateCurrentProgress(Computer.Compute(Import.completeSize), 0.0);
}
}
private static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
FileDownloader.DownloadFile();
}
private enum State
{
REPORT_NAME,
REPORT_PROGRESS,
}
}
and FileDownloader.cs
internal class FileDownloader
{
private static int curFile;
private static long lastBytes;
private static long currentBytes;
private static Stopwatch stopWatch = new Stopwatch();
public static void DownloadFile()
{
if (Import.OldFiles.Count <= 0)
{
Common.ChangeStatus("CHECKCOMPLETE");
Common.UpdateCurrentProgress(100L, 0.0);
Common.UpdateCompleteProgress(100L);
Starter.Start();
}
else if (FileDownloader.curFile >= Import.OldFiles.Count)
{
Common.ChangeStatus("DOWNLOADCOMPLETE");
Common.UpdateCurrentProgress(100L, 0.0);
Common.UpdateCompleteProgress(100L);
Starter.Start();
}
else
{
if (Import.OldFiles[FileDownloader.curFile].Contains("/"))
Directory.CreateDirectory(Path.GetDirectoryName(Import.OldFiles[FileDownloader.curFile]));
WebClient webClient = new WebClient();
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(FileDownloader.webClient_DownloadProgressChanged);
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(FileDownloader.webClient_DownloadFileCompleted);
FileDownloader.stopWatch.Start();
Common.ChangeStatus("DOWNLOADFILE", Import.OldFiles[FileDownloader.curFile]);
webClient.DownloadFileAsync(new Uri(Import.ServerURL + Import.OldFiles[FileDownloader.curFile]), Import.OldFiles[FileDownloader.curFile]);
}
}
private static void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
FileDownloader.currentBytes = FileDownloader.lastBytes + e.BytesReceived;
Common.UpdateCompleteProgress(Computer.Compute(Import.completeSize + FileDownloader.currentBytes));
Common.UpdateCurrentProgress((long) e.ProgressPercentage, Computer.ComputeDownloadSpeed((double) e.BytesReceived, FileDownloader.stopWatch));
}
private static void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
FileDownloader.lastBytes = FileDownloader.currentBytes;
Common.UpdateCurrentProgress(100L, 0.0);
++FileDownloader.curFile;
FileDownloader.stopWatch.Reset();
FileDownloader.DownloadFile();
}
}
Im trying to use the progress bar to track my download, the only problem the progress value changes only after the file is downloaded to the computer and not during its download.
Here is my code, any help will be appreciated.
public void DownloadZaq()
{
using (WebClient zaq = new WebClient())
{
zaq.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Zaq_DownloadProgressChanged);
zaq.DownloadFileCompleted += new AsyncCompletedEventHandler(Zaq_DownloadFileCompleted);
zaq.DownloadFileAsync(new Uri(http://example.com), #"c:\to\111.jpg");
}
}
public void Zaq_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("download completed");
}
public void Zaq_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
I think that DownloadFileAsync is blocking the main thread somehow while checking the DNS. This is what I would try
WebClient zaq;
public void DownloadZaq()
{
zaq = new WebClient();
zaq.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Zaq_DownloadProgressChanged);
zaq.DownloadFileCompleted += new AsyncCompletedEventHandler(Zaq_DownloadFileCompleted);
System.Threading.Tasks.Task.Run(() => // Workaround to allow Async call
{
try
{
zaq.DownloadFileAsync(new Uri(http://example.com), #"c:\to\111.jpg");
}
catch (Exception ex)
{
zag.Dispose();
}
});
}
public void Zaq_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("download completed");
zag.Dispose();
}
public void Zaq_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
I'm sending multiple files to my wrapper which sends files to ftp.I have to get the progress of the upload, so i have to use asycn method for uploading.The problem is, how can i call the uploader one by one, but also get the progress report?
Here's a solution if you want to wait for each file:
class FileUploader
{
private readonly Uri _destination;
public FileUploader(Uri destination)
{
_destination = destination;
}
public void UploadFiles(IEnumerable<string> fileNames)
{
foreach (var fileName in fileNames)
{
UploadFile(fileName);
}
}
private void UploadFile(string fileName)
{
var tcs = new TaskCompletionSource<bool>();
using (var client = new WebClient())
{
client.UploadProgressChanged += UploadProgressChangedHandler;
client.UploadFileCompleted += (sender, args) => UploadCompletedHandler(fileName, tcs, args);
client.UploadFileAsync(_destination, fileName);
tcs.Task.Wait();
}
}
private void UploadCompletedHandler(string fileName, TaskCompletionSource<bool> tcs, UploadFileCompletedEventArgs e)
{
if (e.Cancelled)
{
tcs.TrySetCanceled();
}
else if (e.Error != null)
{
tcs.TrySetException(e.Error);
}
else
{
tcs.TrySetResult(true);
}
}
private void UploadProgressChangedHandler(object sender, UploadProgressChangedEventArgs e)
{
// Handle progress, e.g.
System.Diagnostics.Debug.WriteLine(e.ProgressPercentage);
}
}
You have to subscribe to the UploadProgressChanged event:
var client = new WebClient();
client.UploadProgressChanged += (s, e) => System.Diagnostics.Debug.WriteLine(e.ProgressPercentage);
client.UploadFileAsync(new Uri("ftp://server/directory"), #"C:\temp\file.txt");
client.UploadFileCompleted += (s, e) => Task.Factory.StartNew(client.Dispose);
In my application I want to have my main form(Form1) call a method on my UserControl(EmailControl). Below are the three main methods I am wanting to call:
public void InitializeConnection(string hostname, int port)
{
try
{
_imapClient = new TcpClient(hostname, port);
_imapNs = _imapClient.GetStream();
_imapSw = new StreamWriter(_imapNs);
_imapSr = new StreamReader(_imapNs);
label1.Text = "*** Connected ***";
Response();
}
catch (SocketException ex)
{
Console.WriteLine(ex.Message);
}
}
,
public void AuthenticateUser(string username, string password)
{
_imapSw.WriteLine("$ LOGIN " + username + " " + password);
_imapSw.Flush();
label2.Text = "Logged in";
Response();
}
and
public string MailCount()
{
_imapSw.WriteLine("$ STATUS INBOX (messages)");
_imapSw.Flush();
string res = Response();
Match m = Regex.Match(res, "[0-9]*[0-9]");
return m.ToString();
}
To do this, I am using this on the usercontrol page:
Form1.getemail += new Form1.sendtoemail(this.sendover);
and
public void sendover()
{
InitializeConnection("hostname", 123);
AuthenticateUser("username", "password");
MailCount();
}
Then on my main page I have
public delegate void sendtoemail(object sender, EventArgs e);
public event sendtoemail getemail;
and
private void Form1_Load(object sender, EventArgs e)
{
if (this.getemail != null)
{
this.getemail(this, e);
}
}
After doing this, on my usercontrol page it is telling me that there is no overload for "sendover" matches delegate "sendtoemail", and that I need an object reference. What exactly is throwing the error?
The getemail event is of type sendtoemail, so the function you add as a handler must match that signature.
Here are two solutions:
Change
public void sendover()
to
public void sendover(object sender, EventArgs e)
or change
Form1.getemail += new Form1.sendtoemail(this.sendover);
to
Form1.getemail += (s, e) => sendover();
The first solution changes the signature of sendover to match the delegate type, and the second solution creates an anonymous function with the correct type which calls sendover.
Your method sendover doesn't respect the sendtoemail delegate's method signature:
public delegate void sendtoemail(object sender, EventArgs e); // accepts 2 parameters
Instead of the method declaration:
public void sendover() { // ...
... declare it as...
public void sendover(object sender, EventArgs e) { // ...
I have a GUI-thread for my form and another thread that computes things.
The form has a richtTextBox. I want the worker-thread to pass strings to the form, so that every string is displayed in the textbox.
Everytime a new string is generated in the worker thread I call an event, and this should now display the string.
But I don't know how to pass the string! This is what I tried so far:
///// Form1
private void btn_myClass_Click(object sender, EventArgs e)
{
myClass myObj = new myClass();
myObj.NewListEntry += myObj_NewListEntry;
Thread thrmyClass = new Thread(new ThreadStart(myObj.ThreadMethod));
thrmyClass.Start();
}
private void myObj_NewListEntry(Object objSender, EventArgs e)
{
this.BeginInvoke((MethodInvoker)delegate
{
// Here I want to add my string from the worker-thread to the textbox!
richTextBox1.Text += "TEXT"; // I want: richTextBox1.Text += myStringFromWorkerThread;
});
}
///// myClass (working thread...)
class myClass
{
public event EventHandler NewListEntry;
public void ThreadMethod()
{
DoSomething();
}
protected virtual void OnNewListEntry(EventArgs e)
{
EventHandler newListEntry = NewListEntry;
if (newListEntry != null)
{
newListEntry(this, e);
}
}
private void DoSomething()
{
///// Do some things and generate strings, such as "test"...
string test = "test";
// Here I want to pass the "test"-string! But how to do that??
OnNewListEntry(EventArgs.Empty); // I want: OnNewListEntry(test);
}
}
Like this
public class NewListEntryEventArgs : EventArgs
{
private readonly string test;
public NewListEntryEventArgs(string test)
{
this.test = test;
}
public string Test
{
get { return this.test; }
}
}
then you declare your class like this
class MyClass
{
public delegate void NewListEntryEventHandler(
object sender,
NewListEntryEventArgs args);
public event NewListEntryEventHandler NewListEntry;
protected virtual void OnNewListEntry(string test)
{
if (NewListEntry != null)
{
NewListEntry(this, new NewListEntryEventArgs(test));
}
}
}
and in the subscribing Form
private void btn_myClass_Click(object sender, EventArgs e)
{
MyClass myClass = new MyClass();
myClass.NewListEntry += NewListEntryEventHandler;
...
}
private void NewListEntryEventHandler(
object sender,
NewListEntryEventArgs e)
{
if (richTextBox1.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
this.NewListEntryEventHandler(sender, e);
});
return;
}
richTextBox1.Text += e.Test;
}
I've taken the liberty of making the NewListEntryEventArgs class immutable, since that makes sense. I've also partially corrected your naming conventions, simplified and corrected where expedient.
You need to create a new class by inheriting off EventArgs.
Create your own version of the EventArgs.
Do it like this:
public class MyEventArgs : EventArgs
{
public string MyEventString {get; set; }
public MyEventArgs(string myString)
{
this.MyEventString = myString;
}
}
Then in your code replace the EventArgs with MyEventArgs and create an MyEventArgs object with your string in it.
Then you can access it by using the MyEventArgs instance .MyEventString.
So you would do something like this:
///// myClass (working thread...)
class myClass
{
public event EventHandler NewListEntry;
public void ThreadMethod()
{
DoSomething();
}
protected virtual void OnNewListEntry(MyEventArgs e)
{
EventHandler newListEntry = NewListEntry;
if (newListEntry != null)
{
newListEntry(this, e);
}
}
private void DoSomething()
{
///// Do some things and generate strings, such as "test"...
string test = "test";
OnNewListEntry(new MyEventArgs(test));
}
}
And in your form:
private void myObj_NewListEntry(Object objSender, MyEventArgs e)
{
this.BeginInvoke((MethodInvoker)delegate
{
// Here I want to add my string from the worker-thread to the textbox!
richTextBox1.Text += e.MyEventString;
});
}
In general you need to inherit EventArgs and add a string property, and then make your event of type EventHandler<YourEventArgs>, but that is a classic case for the BackgroundWorker.
Sample here:
http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
and here:
C# backgroundWorker reports string?