我在后台工作者的Windows窗体应用程序中调用asmx服务。我希望能够在按下按钮后取消/停止呼叫。
我目前正在执行以下操作:
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
GlobalVariables.worker = sender as BackgroundWorker;
try
{
if (GlobalVariables.worker.CancellationPending == true)
{
e.Cancel = true;
return;
}
else
{
e.Result = CallServer(ServerName, ActionName); // call on a web method in the referenced service
}
}
catch (Exception ee)
{
GlobalFunctions.ShowError(ee);
}
}
private void button1_Click(object sender, EventArgs e) //button to cancel the call
{
if (GlobalVariables.worker.IsBusy == true)
{
//GlobalVariables.worker.thre;
GlobalVariables.worker.CancelAsync();
GlobalVariables.worker.Dispose();
}
//GlobalVariables.worker.CancelAsync();
Form1.f.Enabled = true;
Form1.f.progressBar1.Text = "Done!";
Form1.f.progressBar1.Visible = false;
Form1.f.textBox1.Visible = true;
Close();
}
以下似乎不起作用,因为当我按下取消时,服务引用中调用的Web方法不会停止并仍然返回数据
答案 0 :(得分:1)
您可以使用Task
和CancellationToken
让客户立即对中止按钮做出反应。客户端将尽力中止呼叫,但服务器将继续执行呼叫,除非它对此做了特别的事情。
以下是客户端的代码:
public partial class Form1 : Form
{
private CancellationTokenSource _cancellationTokenSource;
private WebService1SoapClient _client;
public Form1()
{
InitializeComponent();
btnAbort.Enabled = false;
}
private void btnCall_Click(object sender, EventArgs e)
{
btnCall.Enabled = false;
btnAbort.Enabled = true;
lblStatus.Text = "CALLING SERVER...";
_cancellationTokenSource = new CancellationTokenSource();
_cancellationTokenSource.Token.Register(() => backgroundWorker1.CancelAsync());
backgroundWorker1.RunWorkerAsync();
}
private void btnAbort_Click(object sender, EventArgs e)
{
if (_cancellationTokenSource != null)
{
_cancellationTokenSource.Cancel();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
return;
}
try
{
_client = new WebService1SoapClient();
var call = CallServerAsync("ServerName", "ActionName");
call.Wait(_cancellationTokenSource.Token);
e.Result = call.Result;
}
catch (TaskCanceledException)
{
e.Cancel = true;
_client.Abort();
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnCall.Enabled = true;
btnAbort.Enabled = false;
lblStatus.Text = (e.Error != null ? "CALL FAILED: " + e.Error.Message : "CALL COMPLETED!");
}
private async Task<string> CallServerAsync(string serverName, string actionName)
{
var response = await _client.HelloWorldAsync();
return response.Body.HelloWorldResult;
}
}
答案 1 :(得分:0)
此问题已在此处提出并回答
答案 2 :(得分:0)
感谢@ felix-b回答,我做了以下事情:
public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
GlobalVariables.worker = sender as BackgroundWorker;
try
{
if (GlobalVariables.worker.CancellationPending == true)
{
e.Cancel = true;
return;
}
else
{
Object callResponse = CallServer(ServerName, ActionName);
if (GlobalVariables.worker.CancellationPending == true)
{
e.Cancel = true;
return;
}
else
{
e.Result = callResponse;
}
}
}
catch (Exception ee)
{
e.Cancel = true;
if (ee.GetType().IsAssignableFrom(typeof(System.ServiceModel.CommunicationObjectAbortedException)))
{
MessageBox.Show("The Request Was Cancelled");
}
else
{
GlobalFunctions.ShowError(ee);
}
}
}
public void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{}
else
{
//continue
}
}
private void button1_Click(object sender, EventArgs e)
{
if (GlobalVariables.worker.IsBusy == true)
{
server.abort(); //service reference
GlobalVariables.worker.CancelAsync();
GlobalVariables.worker.Dispose();
}
}