我有一个下载货币汇率的表单,该方法以异步方式运行。现在我需要在用户关闭窗口时停止该方法。我找到了一个解决方案here,但未能在我的代码中实现它。这是我的完整代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Globalization;
using System.Xml;
using System.Data.SqlClient;
using System.Threading;
namespace ProjectPro
{
public partial class GetRatesForPeriod : Form
{
public GetRatesForPeriod()
{
InitializeComponent();
}
private void closeBut_Click(object sender, EventArgs e)
{
this.Close();
}
CancellationTokenSource cts;
private async void runBut_Click(object sender, EventArgs e)
{
try
{
cts = new CancellationTokenSource();
this.runBut.Enabled = false;
for (DateTime d = fromDatePicker.Value.Date; d <= toDatePicker.Value.Date; d = d.AddDays(1))
{
if (d.DayOfWeek == DayOfWeek.Saturday || d.DayOfWeek == DayOfWeek.Sunday)
continue;
switch(StaticValues.user.Language)
{
case "English":
this.statusLab.Text = "Updating rates: " + d.Date.ToShortDateString();
break;
case "Russian":
this.statusLab.Text = "Обновление курса валют: " + d.Date.ToShortDateString();
break;
case "Azeri":
this.statusLab.Text = "Məzənnələr yenilənir: " + d.Date.ToShortDateString();
break;
default:
break;
}
string url = "http://cbar.az/currencies/" + d.ToString("dd.MM.yyyy", CultureInfo.InvariantCulture) + ".xml";
#region read rates for the date to the DataTable
var slowTask = Task<XmlDocument>.Factory.StartNew(() => GetXmlAsync(url, cts.Token));
await slowTask;
XmlDocument doc = slowTask.Result;
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("//ValCurs/ValType");
DataTable tempRates = new DataTable();
foreach (XmlNode node in nodes)
{
if (node.Attributes["Type"].Value == "Xarici valyutalar")
{
//create temp table and load new rates
tempRates.Clear();
tempRates.Columns.Add("Code");
tempRates.Columns.Add("Nominal");
tempRates.Columns.Add("Name");
tempRates.Columns.Add("Value");
foreach (XmlNode currency in node.ChildNodes)
{
DataRow dr = tempRates.NewRow();
dr["Code"] = currency.Attributes["Code"].Value;
foreach (XmlNode currencyDetailsNode in currency.ChildNodes)
{
dr[currencyDetailsNode.Name] = currencyDetailsNode.InnerText;
}
tempRates.Rows.Add(dr);
}
}
}
#endregion
DAL dal = new DAL();
dal.ClearCurrentRates(d);
//insert new values
foreach (DataRow currencyRow in StaticValues.dataSet.Tables["Currencies"].Rows)
{
if (currencyRow["Code"].ToString() == "AZN")
{
#region Insert the row for AZN
try
{
SqlParameter[] pars = new SqlParameter[3];
pars[0] = new SqlParameter("@Date", SqlDbType.Date);
pars[0].Value = d.ToShortDateString();
pars[1] = new SqlParameter("@currencyCode", SqlDbType.NVarChar);
pars[1].Value = currencyRow[1].ToString();
pars[2] = new SqlParameter("@Rate", SqlDbType.Decimal);
pars[2].Value = 1;
dal.InsertData("CurrencyRates", pars);
}
catch (Exception ex)
{
StaticValues.WriteEventLogXML(ex, this.Text);
switch (StaticValues.user.Language)
{
case "English":
MessageBox.Show("Database error", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case "Russian":
MessageBox.Show("Ошибка базы данных", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case "Azeri":
MessageBox.Show("Məlumat bazası səhvi", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
default:
break;
}
}
#endregion
continue;
}
foreach (DataRow tempRow in tempRates.Rows)
{
if (tempRow["Code"].ToString() == currencyRow["Code"].ToString())
{
#region Insert the row
try
{
SqlParameter[] pars = new SqlParameter[3];
pars[0] = new SqlParameter("@Date", SqlDbType.Date);
pars[0].Value = d.ToShortDateString();
pars[1] = new SqlParameter("@currencyCode", SqlDbType.NVarChar);
pars[1].Value = currencyRow[1].ToString();
pars[2] = new SqlParameter("@Rate", SqlDbType.Decimal);
pars[2].Value = decimal.Parse(tempRow["Value"].ToString(), CultureInfo.InvariantCulture);
dal.InsertData("CurrencyRates", pars);
break;
}
catch (Exception ex)
{
StaticValues.WriteEventLogXML(ex, this.Text);
switch (StaticValues.user.Language)
{
case "English":
MessageBox.Show("Database error", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case "Russian":
MessageBox.Show("Ошибка базы данных", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case "Azeri":
MessageBox.Show("Məlumat bazası səhvi", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
default:
break;
}
break;
}
#endregion
}
}
}
Thread.Sleep(1000);
}
}
catch (OperationCanceledException ex)
{
StaticValues.WriteEventLogXML(ex, this.Text);
switch (StaticValues.user.Language)
{
case "English":
this.statusLab.Text = "Cancelled";
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case "Russian":
this.statusLab.Text = "Готово";
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case "Azeri":
this.statusLab.Text = "Dayandırılıb.";
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
default:
break;
}
}
catch (Exception ex)
{
StaticValues.WriteEventLogXML(ex, this.Text);
switch (StaticValues.user.Language)
{
case "English":
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case "Russian":
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case "Azeri":
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
default:
break;
}
}
finally
{
switch (StaticValues.user.Language)
{
case "English":
this.statusLab.Text = "Ready";
break;
case "Russian":
this.statusLab.Text = "Готово";
break;
case "Azeri":
this.statusLab.Text = "Hazır";
break;
default:
break;
}
this.runBut.Enabled = true;
}
}
private XmlDocument GetXmlAsync(string url, CancellationToken tok)
{
XmlDocument doc = new XmlDocument();
doc.Load(url);
return doc;
}
private void GetRatesForPeriod_FormClosing(object sender, FormClosingEventArgs e)
{
if (cts != null)
cts.Cancel();
}
}
}
答案 0 :(得分:0)
问题出在这里:
private XmlDocument GetXmlAsync(string url, CancellationToken tok)
{
XmlDocument doc = new XmlDocument();
doc.Load(url);
return doc;
}
XmlDocument不是异步的,根本也不使用取消令牌。您必须修改此方法才能异步加载URL。一个候选人可能是使用HttpClient
。我在这里找到了一个可能有用的例子。