C#.Net - 如何取消从 WebService 拉取数据的 BackgroundWorker

3
我有以下代码:
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。现在,由于我没有循环,所以我看不到一种检查取消的好方法。我唯一能想到的选择是...

byte[] m_CurrentData;

在方法之外启动一个新线程,在DoWork(..)的开始调用webservice来填充m_CurrentData。然后需要执行循环检查是否已取消或检查m_CurrentData是否不再为空。
有更好的实现取消的方法吗?
2个回答

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

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


太简单了!只需调用 WebService.Abort() 并捕获异常即可!谢谢! - djdd87

1

更新

我刚刚查看了DoWorkEventArgs的MSDN,意识到我之前的答案是错误的。在BackgroundWorker上有一个CancellationPending属性,它由对CancelAsync的调用设置(来自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。 - djdd87
啊 - 我看了,但显然没有完全理解你问题的那部分。我会尝试更新答案。 - ChrisF

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接