C#.Net - 如何取消BackgroundWorker从WebService中提取数据

发布于 2024-07-23 01:16:20 字数 1287 浏览 8 评论 0原文

我有以下代码:

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(..) 开始时启动一个新线程,该线程调用 Web 服务来填充 m_CurrentData。 然后我需要执行循环检查是否被取消或检查 m_CurrentData 是否不再为空。

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

I've got the following code:

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;
    }
}

The code is basically calling a delegate to a WebService method. Unfortunately, the main reason I used a background worker was to stop the UI freezing when loading the data. I've got a form that pops up saying please wait, click here to cancel.

On the click of cancel I call CancelAsync on the background worker. Now, as I'm not looping I cannot see a nice way of checking for a cancellation. The only option I can see is to have...

byte[] m_CurrentData;

...outside of the method and launch a new thread on the start of DoWork(..) that calls the webservice to populate m_CurrentData. I'd then need to perform a loop checking if cancelled or checking if m_CurrentData is no longer null.

Is there any better way of achieving a cancellation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晚雾 2024-07-30 01:16:21

更新

我刚刚检查了MSDN for DoWorkEventArgs 并意识到我之前的答案是错误的。 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;
    }
}

你能使用这个吗?

Update

I've just checked the MSDN for DoWorkEventArgs and realised that my previous answer was wrong. There's the CancellationPending property on the BackgroundWorker which is set by by the call to CancelAsync (from the MSDN). Thus your DoWork method can become:

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;
    }
}

Can you use this?

羁绊已千年 2024-07-30 01:16:20

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

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

The actual work seems to be done inside the this.GetData(...) method which is not shown. I gather it is calling a webservice. You probably should call the Abort() method on the proxy object to stop the client from waiting for the response. There is no point in calling CancelAsync(), just be sure to correctly check for errors in RunWorkerCompleted(). The easiest way is probably not to catch any exceptions in _DoWork(), but check the Result.Error property in Completed(). You should do that anyway.

Just to clarify, the CancelAsync() method is only useful to stop a loop inside DoWork(). You are not running a (meaningful) loop there, so another approach is needed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文