How cancel Downloading Async? - c#

I've got a problem. How can I cancel a download ?
client.CancelAsync();
Doesn't work for me, because if I cancel a download and start a new one the code still tries to access the old download file. You've to know in my code is a part when a download is done it should unzip the file which has been downloaded. Example.zip like this :)
So, when I cancel my download and start a new one you know my script tries to unzip my old Example.zip, but it should kick this ....
For Unzipping, I'm using Iconic.Zip.dll (http://dotnetzip.codeplex.com/)
How to get it work?
UPDATE:
This is my Downloader Form
private void button3_Click_1(object sender, EventArgs e)
{
DialogResult dialogResult = MessageBox.Show("This will cancel your current download ! Continue ?", "Warning !", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
cancelDownload = true;
URageMainWindow.isDownloading = false;
this.Close();
}
else if (dialogResult == DialogResult.No)
{
}
}
This is my Main form this happens when you start downloading something
private void checkInstall(object sender, WebBrowserDocumentCompletedEventArgs e)
{
string input = storeBrowser.Url.ToString();
// Test these endings
string[] arr = new string[]
{"_install.html"};
// Loop through and test each string
foreach (string s in arr)
{
if (input.EndsWith(s) && isDownloading == false)
{
// MessageBox.Show("U.Rage is downloading your game");
Assembly asm = Assembly.GetCallingAssembly();
installID = storeBrowser.Document.GetElementById("installid").GetAttribute("value");
// MessageBox.Show("Name: " + installname + " ID " + installID);
installname = storeBrowser.Document.GetElementById("name").GetAttribute("value");
installurl = storeBrowser.Document.GetElementById("link").GetAttribute("value");
isDownloading = true;
string install_ID = installID;
string Install_Name = installname;
// MessageBox.Show("New Update available ! " + " - Latest version: " + updateversion + " - Your version: " + gameVersion);
string url = installurl;
WebClient client = new WebClient();
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_InstallProgressChanged);
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_InstallFileCompleted);
client.DownloadFileAsync(new Uri(url), #"C:\U.Rage\Downloads\" + installID + "Install.zip");
if (Downloader.cancelDownload == true)
{
//MessageBox.Show("Downloader has been cancelled");
client.CancelAsync();
Downloader.cancelDownload = false;
}
notifyIcon1.Visible = true;
notifyIcon1.ShowBalloonTip(2, "Downloading !", "U.Rage is downloading " + installname, ToolTipIcon.Info);
System.Media.SoundPlayer player = new System.Media.SoundPlayer(#"c:/U.Rage/Sounds/notify.wav");
player.Play();
storeBrowser.GoBack();
igm = new Downloader();
igm.labelDWGame.Text = installname;
// this.Hide();
igm.Show();
return;
}
if (input.EndsWith(s) && isDownloading == true)
{
System.Media.SoundPlayer player = new System.Media.SoundPlayer(#"c:/U.Rage/Sounds/notify.wav");
player.Play();
MessageBox.Show("Please wait until your download has been finished", "Warning");
storeBrowser.GoBack();
}
}
}
This happens when the download has been finished
void client_InstallFileCompleted(object sender, AsyncCompletedEventArgs e)
{
if(Downloader.cancelDownload == false)
{
using (ZipFile zip = ZipFile.Read(#"C:\U.Rage\Downloads\" + installID + "Install.zip"))
{
//zip.Password = "iliketrains123";
zip.ExtractAll("C:/U.Rage/Games/", ExtractExistingFileAction.OverwriteSilently);
}
System.IO.File.Delete(#"C:/U.Rage/Downloads/" + installID + "Install.zip");
notifyIcon1.Visible = true;
notifyIcon1.ShowBalloonTip(2, "Download Completed !", "Installing was succesful !", ToolTipIcon.Info);
System.Media.SoundPlayer player = new System.Media.SoundPlayer(#"c:/U.Rage/Sounds/notify.wav");
player.Play();
this.Show();
igm.Close();
isDownloading = false;
listView.Items.Clear();
var files = Directory.GetFiles(#"C:\U.Rage\Games\", "*.ugi").Select(f => new ListViewItem(f)).ToArray();
foreach (ListViewItem f in files)
{
this.LoadDataFromXml(f);
}
}
}

Here is the method for async data download that supports cancellation:
private static async Task<byte[]> downloadDataAsync(Uri uri, CancellationToken cancellationToken)
{
if (String.IsNullOrWhiteSpace(uri.ToString()))
throw new ArgumentNullException(nameof(uri), "Uri can not be null or empty.");
if (!Uri.IsWellFormedUriString(uri.ToString(), UriKind.Absolute))
return null;
byte[] dataArr = null;
try
{
using (var webClient = new WebClient())
using (var registration = cancellationToken.Register(() => webClient.CancelAsync()))
{
dataArr = await webClient.DownloadDataTaskAsync(uri);
}
}
catch (WebException ex) when (ex.Status == WebExceptionStatus.RequestCanceled)
{
// ignore this exception
}
return dataArr;
}

When you call CancelAsync, the AsyncCompletedEventArgs object passed to the completed callback will have the Cancelled property set to true. So you could write:
void client_InstallFileCompleted(object sender, AsyncCompletedEventArgs e)
{
if(e.Cancelled)
{
// delete the partially-downloaded file
return;
}
// unzip and do whatever...
using (ZipFile zip = ZipFile.Read(#"C:\U.Rage\Downloads\" + installID + "Install.zip"))
See the documentation for more info.

The selected answer didn't work properly for me. Here's what I did:
When they click the cancel button I call the
Client.CancelAsync();
And then in the Web.Client DownloadFileCompleted:
Client.DownloadFileCompleted += (s, e) =>
{
if (e.Cancelled)
{
//cleanup delete partial file
Client.Dispose();
return;
}
}
And then when you try to re-download just instantiate a new client:
Client = WebClient();
This way the old async parameters won't be maintained.

Related

C#Webclient downloadfileasync not working

/// <summary>
/// 下载更新
/// </summary>
public string Update()
{
string result = "";
try
{
if (!isUpdate)
return result;
WebClient wc = new WebClient();
string filename = "Update_NewVersion.zip";
filename = Path.GetDirectoryName(loadFile) + "\\" + filename;
FinalZipName = filename;
//wc.DownloadFile(download, filename);//能下载成功
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
wc.DownloadFileAsync(new Uri(download), filename);//使用DownloadFileAsync下载不成功,能正常运行代码,但是执行后没有下载到zip文件,
//wc.Dispose();
return result = "download:" + download + ",filename:" + filename;
}
catch (Exception ex)
{
throw new Exception("更新出现错误,网络连接失败!" + ex.Message);
}
}
void wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
(sender as WebClient).Dispose();
if (e.Error != null)
throw e.Error;
else
isFinish();
}
void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
CommonMethod.autostep = e.ProgressPercentage;
//Thread.Sleep(100);
}
The download file code using downloadfileasync works normally, but it is not downloaded to the file after execution. It has been tested that downloadfile can be downloaded to the file normally。
Is it because the program completed the running before the download finished? It is a possible reason if your app is a console application.
Following comes from mdsn:
https://learn.microsoft.com/en-us/dotnet/api/system.net.webclient.downloadfileasync?view=net-5.0
This method does not block the calling thread while the resource is being downloaded. To block while waiting for the download to complete, use one of the DownloadFile methods.

Skydrive wp7 App: GetAsync method stopped working

On my windows phone 7 Mango app I use the Microsoft.Live and Microsoft.Live.Controls references to download and upload on Skydrive. Logging in and uploading files works fine but whenever I call the "client.GetAsync("/me/skydrive/files");" on the LiveConnectClient the Callback result is empty just containing the error: "An error occurred while retrieving the resource. Try again later."
I try to retrieve the list of files with this method.
This error suddenly occured without any change on the source code of the app (I think..) which worked perfectly fine for quite a while until recently. At least I didn't change the code section for up- or downloading.
I tried out the "two-step verification" of Skydrive, still the same: can log in but not download.
Also updating the Live refercences to 5.5 didn't change anything.
Here is the code I use. The error occurs in the "getDir_Callback" in the "e" variable.
Scopes (wl.skydrive wl.skydrive_update) and clientId are specified in the SignInButton which triggers "btnSignin_SessionChanged".
private void btnSignin_SessionChanged(object sender, LiveConnectSessionChangedEventArgs e)
{
if (e.Status == LiveConnectSessionStatus.Connected)
{
connected = true;
processing = true;
client = new LiveConnectClient(e.Session);
client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(OnGetCompleted);
client.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(UploadCompleted);
client.DownloadCompleted += new EventHandler<LiveDownloadCompletedEventArgs>(OnDownloadCompleted);
client.DownloadProgressChanged += new EventHandler<LiveDownloadProgressChangedEventArgs>(client_DownloadProgressChanged);
infoTextBlock.Text = "Signed in. Retrieving file IDs...";
client.GetAsync("me");
}
else
{
connected = false;
infoTextBlock.Text = "Not signed into Skydrive.";
client = null;
}
}
private void OnGetCompleted(object sender, LiveOperationCompletedEventArgs e)
{
if (e.Error == null)
{
client.GetCompleted -= new EventHandler<LiveOperationCompletedEventArgs>(OnGetCompleted);
client.GetCompleted += getDir_Callback;
client.GetAsync("/me/skydrive/files");
client_id = (string)e.Result["id"];
if (e.Result.ContainsKey("first_name") && e.Result.ContainsKey("last_name"))
{
if (e.Result["first_name"] != null && e.Result["last_name"] != null)
{
infoTextBlock.Text = "Hello, " +
e.Result["first_name"].ToString() + " " +
e.Result["last_name"].ToString() + "!";
}
}
else
{
infoTextBlock.Text = "Hello, signed-in user!";
}
}
else
{
infoTextBlock.Text = "Error calling API: " +
e.Error.ToString();
}
processing = false;
}
public void getDir_Callback(object s, LiveOperationCompletedEventArgs e)
{
client.GetCompleted -= getDir_Callback;
//filling Dictionary with IDs of every file on SkyDrive
if (e.Result != null)
ParseDir(e);
if (!String.IsNullOrEmpty(e.Error.Message))
infoTextBlock.Text = e.Error.Message;
else
infoTextBlock.Text = "File-IDs loaded";
}
Yo shall use client.GetAsync("me/SkyDrive/files", null) in place of client.GetAsync("me");
This is my code and it works fine.
private void btnSignIn_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e)
{
try
{
if (e.Session != null && e.Status == LiveConnectSessionStatus.Connected)
{
client = new LiveConnectClient(e.Session);
client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(client_GetCompleted);
client.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(client_UploadCompleted);
client.GetAsync("me/SkyDrive/files", null);
client.DownloadAsync("me/SkyDrive", null);
canUpload = true;
ls = e.Session;
}
else
{
if (client != null)
{
MessageBox.Show("Signed out successfully!");
client.GetCompleted -= client_GetCompleted;
client.UploadCompleted -= client_UploadCompleted;
canUpload = false;
}
else
{
canUpload = false;
}
client = null;
canUpload = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void client_GetCompleted(object sender, LiveOperationCompletedEventArgs e)
{
try
{
List<System.Object> listItems = new List<object>();
if (e.Result != null)
{
listItems = e.Result["data"] as List<object>;
for (int x = 0; x < listItems.Count(); x++)
{
Dictionary<string, object> file1 = listItems[x] as Dictionary<string, object>;
string fileName = file1["name"].ToString();
if (fileName == lstmeasu[0].Title)
{
folderID = file1["id"].ToString();
folderAlredyPresent = true;
}
}
}
}
catch (Exception)
{
MessageBox.Show("An error occured in getting skydrive folders, please try again later.");
}
}
It miraculously works again without me changing any code. It seems to be resolved on the other end. I have no clue what was wrong.

Using a label to depict the status of a form

I have a situation where all I need is a label that switches between "Ready" and "In progress" when a user clicks a button. The label is intially in the "Ready" state. When the user clicks a button, the label should read "In progress" then some tasks need to be performed, like copying files etc. After the tasks are completed successfully the label should once again read "Ready". Right now I am using this piece of code and the label status does not change. How can I make this work. Please help.
private void button1_Click(object sender, EventArgs e)
{
status.Text = "In Progress";
if (listBox1.Items.Count == 0)
{
MessageBox.Show("Please select a file to upload");
}
FtpClient client = new FtpClient("*******", "*******", "******");
string fileName = getFileNameFromPath(listBox1.Items[0].ToString());
string localFile = listBox1.Items[0].ToString();
string remoteFile = "**********/"+fileName;
string link = client.upload(remoteFile, localFile);
listBox1.Items.RemoveAt(0);
textBox1.Text = link;
status.Text = "Ready";
}
You're blocking the UI thread during your long running process, both preventing the UI from updating the text value, or receiving user input, or doing anything for that matter.
You need to do the long running work asynchronously so as to not block the UI thread.
Ideally you'd have an asynchronous method provided by your FtpClient (and even better, it would return a Task). This would allow you to write something like this:
private async void button1_Click(object sender, EventArgs e)
{
status.Text = "In Progress";
if (listBox1.Items.Count == 0)
{
MessageBox.Show("Please select a file to upload");
}
FtpClient client = new FtpClient("*******", "*******", "******");
string fileName = getFileNameFromPath(listBox1.Items[0].ToString());
string localFile = listBox1.Items[0].ToString();
string remoteFile = "**********/" + fileName;
string link = await client.uploadAsync(remoteFile, localFile);
listBox1.Items.RemoveAt(0);
textBox1.Text = link;
status.Text = "Ready";
}
And then you'd be done. If it doesn't provide any asynchronous methods then, as a work around, you can just start up a new task to do the work in the background:
private async void button1_Click(object sender, EventArgs e)
{
status.Text = "In Progress";
if (listBox1.Items.Count == 0)
{
MessageBox.Show("Please select a file to upload");
}
FtpClient client = new FtpClient("*******", "*******", "******");
string fileName = getFileNameFromPath(listBox1.Items[0].ToString());
string localFile = listBox1.Items[0].ToString();
string remoteFile = "**********/" + fileName;
string link = await Task.Run(() => client.upload(remoteFile, localFile));
listBox1.Items.RemoveAt(0);
textBox1.Text = link;
status.Text = "Ready";
}
If you don't have C# 5.0 and .NET 4.5 to be able to use await then you can use a BackgroundWorker:
private void button1_Click(object sender, EventArgs e)
{
status.Text = "In Progress";
if (listBox1.Items.Count == 0)
{
MessageBox.Show("Please select a file to upload");
}
string fileName = getFileNameFromPath(listBox1.Items[0].ToString());
string localFile = listBox1.Items[0].ToString();
string remoteFile = "**********/" + fileName;
var worker = new BackgroundWorker();
worker.DoWork += (s, args) =>
{
FtpClient client = new FtpClient("*******", "*******", "******");
args.Result = client.upload(remoteFile, localFile);
};
worker.RunWorkerCompleted += (s, args) =>
{
listBox1.Items.RemoveAt(0);
textBox1.Text = args.Result as string;
status.Text = "Ready";
};
worker.RunWorkerAsync();
}

C# Webclient not working properly

I've created a simple tool that can find Sign up option in websites (200 website list is in arraylist).
I was using webbrowser but it has a problem of cache and cookie so i switched to webclient. It works fine when i put breakpoints and debug but when i run it normally, it also include those websites which doesn't have signup option.
Here is my code
private void btnSearch_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
timer1.Start();
}
Timer1 code
string st;
private void timer1_Tick(object sender, EventArgs e)
{
st = "";
Application.DoEvents();
try
{
st = lst[dataindex2].ToString();
using (WebClient asyncWebRequest = new WebClient())
{
asyncWebRequest.DownloadDataCompleted += asyncWebRequest_DownloadDataCompleted;
Uri urlToRequest = new Uri(st);
asyncWebRequest.DownloadDataAsync(urlToRequest);
asyncWebRequest.Dispose();
}
dataindex2++;
if (dataindex2 == lst.Count)
{
timer1.Stop();
lblStatus.Text = "Stopped";
lblStatus.ForeColor = Color.DarkRed;
MessageBox.Show("Search Completed");
}
}
catch (Exception ex)
{
timer1.Stop();
lblStatus.Text = "Stopped";
lblStatus.ForeColor = Color.DarkRed;
timer1.Dispose();
MessageBox.Show(ex.Message);
return;
}
asyncWebRequest_DownloadDataCompleted code:
private void asyncWebRequest_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
if (e.Error != null)
{
timer1.Stop();
ena();
lblStatus.Text = "Stopped";
lblStatus.ForeColor = Color.DarkRed;
timer1.Dispose();
MessageBox.Show(e.Error.Message);
}
if (e.Result != null && e.Result.Length > 0)
{
string browsetext = "";
int = iSuccess = 0;
browsetext = Encoding.Default.GetString(e.Result);
iSuccess = browsetext.IndexOf("Sign up") + 1;
if (iSuccess == 0)
{
}
else
{
listBox1.Items.Add(st);
domaincount++;
lblDomainCount.ForeColor = Color.DarkGreen;
lblDomainCount.Text = domaincount.ToString();
}
}
else
{
}
}
}
else
{
MessageBox.Show("No data found.");
}
}
Please help and if there is any alternate of webclient that doesn't hang gui then please suggest. ty.
You dispose WebClient as soon as you start the download.
asyncWebRequest.DownloadDataAsync(urlToRequest);
asyncWebRequest.Dispose();
Please help and if there is any alternate of webclient that doesn't hang gui
see my other answer which creates a wrapper for WebClient to be able to use async/await. HttpClient can be an alternative too.

Icon doesn't update when a messagebox is shown at Form1.Load

In Form1.Load, I have:
MessageBox.Show("Text blah blah blah");
Until you press OK, this is the icon in the Taskbar:
When you press OK, it changes to the icon:
How do I make it update when it starts?
I changed the icon by changing it in the form properties:
Entire "Load" function:
string word = "1.4";
var url = "http://chipperyman573.com/rtf/textbot.html";
var client = new WebClient();
using (var stream = client.OpenRead(url))
using (var reader = new StreamReader(stream))
{
string downloadedString;
while ((downloadedString = reader.ReadLine()) != null)
{
if (downloadedString == word)
{
update = false;
MessageBox.Show("Congrats! You are running the latest version (" + word + ") of Chip Bot!\n\nGot an idea for this program? Use the \"Send feedback\" button to let me know!", "Chip Bot", MessageBoxButtons.OK, MessageBoxIcon.Information);
Text = "Chip Bot" + word + " - Got an idea for this program? Send me some feedback!";
}
else
{
Text = "Chip Bot (UPDATE AVAILABLE)";
go.ForeColor = Color.Gray;
setup.Enabled = false;
otherGroup.Enabled = false;
optionsGroup.Enabled = false;
MessageBox.Show("There is an update! Downloading now! \n\nUNTIL YOU UPDATE THE PROGRAM WILL NOT FUNCTION.", "Chip Bot", MessageBoxButtons.OK, MessageBoxIcon.Information);
url = "";
var web = new WebBrowser();
web.Navigate(url);
}
}
}
It does it regardless of if there is an update (downloadstring != word) or if there isn't one (downloadstring == word)
Try using the Shown event instead, and I fixed your code with the wrong use of the WebClient (I used DownloadStringAsync):
private void Form1_Shown(Object s1, EventArgs e1) {
string word = "1.4";
var url = "http://chipperyman573.com/rtf/textbot.html";
var client = new WebClient();
client.DownloadStringCompleted += (s2, e2) =>
{
if(e2.Error != null)
{
//Maybe do some error handling?
}
else
{
if (e2.Result == word)
{
update = false;
MessageBox.Show("Congrats! You are running the latest version (" + word + ") of Chip Bot!\n\nGot an idea for this program? Use the \"Send feedback\" button to let me know!", "Chip Bot", MessageBoxButtons.OK, MessageBoxIcon.Information);
Text = "Chip Bot" + word + " - Got an idea for this program? Send me some feedback!";
}
else
{
Text = "Chip Bot (UPDATE AVAILABLE)";
go.ForeColor = Color.Gray;
setup.Enabled = false;
otherGroup.Enabled = false;
optionsGroup.Enabled = false;
MessageBox.Show("There is an update! Downloading now! \n\nUNTIL YOU UPDATE THE PROGRAM WILL NOT FUNCTION.", "Chip Bot", MessageBoxButtons.OK, MessageBoxIcon.Information);
url = "";
var web = new WebBrowser();
web.Navigate(url);
}
}
};
client.DownloadStringAsync(new Uri(url, UriKind.Absolute));
}

Categories

Resources