【问题标题】:C#.Net - How to cancel a BackgroundWorker pulling data from a WebServiceC#.Net - 如何取消 BackgroundWorker 从 WebService 中提取数据
【发布时间】:2009-06-09 19:30:09
【问题描述】:

我有以下代码:

void ReferenceManager_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {

        // Get the raw data
        byte[] data = this.GetData(IvdSession.Instance.Company.Description, IvdSession.Instance.Company.Password);

        // Deserialize the list
        List<T> deseriaizedList = null;
        using (MemoryStream ms = new MemoryStream(data))
        {
            deseriaizedList = Serializer.Deserialize<List<T>>(ms);
        }

        // Convert the list to the Reference Interface
        List<IReference> referenceList = new List<IReference>();
        foreach (T entity in deseriaizedList)
        {
            IReference reference = (IReference)entity;
            referenceList.Add(reference);
        }

        e.Result = referenceList;

    }
    catch (WebException)
    {
        e.Result = null;
    }
}

代码基本上是调用 WebService 方法的委托。不幸的是,我使用后台工作者的主要原因是在加载数据时停止 UI 冻结。我有一个弹出的表格说请稍候,点击这里取消。

点击取消后,我在后台工作人员上调用 CancelAsync。现在,由于我没有循环播放,我看不到检查取消的 nice 方法。我能看到的唯一选择是...

byte[] m_CurrentData;

...在方法之外并在 DoWork(..) 开始时启动一个新线程,该线程调用 web 服务来填充 m_CurrentData。然后我需要执行循环检查是否取消或检查 m_CurrentData 是否不再为空。

有没有更好的方法来实现取消?

【问题讨论】:

    标签: c# web-services multithreading backgroundworker


    【解决方案1】:

    实际工作似乎是在未显示的this.GetData(...) 方法中完成的。我收集它正在调用网络服务。您可能应该在代理对象上调用Abort() 方法来阻止客户端等待响应。调用CancelAsync() 没有任何意义,只要确保正确检查RunWorkerCompleted() 中的错误即可。最简单的方法可能是捕获_DoWork() 中的任何异常,而是检查Completed() 中的Result.Error 属性。无论如何你都应该这样做。

    澄清一下,CancelAsync() 方法仅用于在 DoWork() 中停止循环。您没有在那里运行(有意义的)循环,因此需要另一种方法。

    【讨论】:

    • 这么简单!只需调用 WebService.Abort() 并捕获异常!谢谢!
    【解决方案2】:

    更新

    我刚刚检查了MSDN for DoWorkEventArgs 并意识到我之前的答案是错误的。 BackgroundWorker 上的 CancellationPending 属性由对 CancelAsync (from the MSDN) 的调用设置。因此你的DoWork 方法可以变成:

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        // Do not access the form's BackgroundWorker reference directly.
        // Instead, use the reference provided by the sender parameter.
        BackgroundWorker bw = sender as BackgroundWorker;
    
        // Extract the argument.
        int arg = (int)e.Argument;
    
        // Start the time-consuming operation.
        e.Result = TimeConsumingOperation(bw, arg);
    
        // If the operation was canceled by the user, 
        // set the DoWorkEventArgs.Cancel property to true.
        if (bw.CancellationPending)
        {
            e.Cancel = true;
        }
    }
    

    你可以用这个吗?

    【讨论】:

    • 您好,DoWork 有提供取消通知的 e.Cancel。我的方法没有循环,所以无法检查 e.Cancel 是否已更改为 true。
    • 啊 - 我读过,但显然没有完全理解你问题的那一部分。我会看看我是否可以更新答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 2012-03-27
    • 2018-03-18
    • 2015-01-21
    • 1970-01-01
    • 2023-03-23
    • 2016-12-13
    相关资源
    最近更新 更多