在后台工作程序C#中取消服务引用调用

时间:2016-07-18 11:08:30

标签: c# service-reference

我在后台工作者的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方法不会停止并仍然返回数据

3 个答案:

答案 0 :(得分:1)

您可以使用TaskCancellationToken让客户立即对中止按钮做出反应。客户端将尽力中止呼叫,但服务器将继续执行呼叫,除非它对此做了特别的事情。

以下是客户端的代码:

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)

此问题已在此处提出并回答

Cancel async web service calls

答案 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();
    }
}