ExecuteAsync RestSharp允许backgroundWorker CancellationPending C# [英] ExecuteAsync RestSharp to allow backgroundWorker CancellationPending c#

查看:100
本文介绍了ExecuteAsync RestSharp允许backgroundWorker CancellationPending C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是C#,RestSharp和线程技术的新手,所以这里是我想做的事情:
我已经制作了一个程序,可以将照片上传到tumblr,并且到目前为止,我可以进行上传.现在我需要停止按钮才能工作,我相信这意味着我必须使用ExecuteAsync()而不是Execute(). 我也将代码放入了一个背景工作器中,如下所示:

I'm new to C#, RestSharp, and threading, so heres what I'm trying to do:
I have made a program that will allow me to upload photos to tumblr, and I have the uploading working so far. Now I need the stop button to work, which I believe means I must use ExecuteAsync() instead of Execute(). I also have my code put in a backgroundworker, like this:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    if (backgroundWorker1.CancellationPending)
    {
        e.Cancel = true;
        MessageBox.Show("You pressed Cancel.");
    }
    else
    {
    var restClient = new RestClient("http://tumblr.com/api/write");
    foreach (string item in queueBox.Items)
    {
        var request = new RestRequest(Method.POST);
        request.RequestFormat = DataFormat.Json; //I don't know if this line is necessary
        request.AddParameter("email", usernameBox.Text);
        request.AddParameter("password", passwordBox.Text);
        request.AddParameter("type", "photo");
        request.AddFile("data", FolderName + "\\" + item);
        RestResponse response = restClient.Execute(request);
        doneBox.Invoke(new UpdateTextCallback(this.UpdateText),
            new object[] { item });
    }
    }
}

我相信我已经正确设置了.当我按upload时,它会相应地转到else.但是,我认为RestResponse response = restClient.Execute(request);这是阻塞的,这不允许我的代码继续检查该标志.

这就是我尝试取消它的方式.

I believe I have set this up correctly. When I press upload it goes to else accordingly. However, I think that RestResponse response = restClient.Execute(request); this is blocking, which isn't allowing my code to continue checking the flag.

This is how I attempt to cancel it.

public void stopButton_Click(object sender, EventArgs e)
{
    doneBox.Items.Add("You pressed the stop button.");
    backgroundWorker1.WorkerSupportsCancellation = true;
    backgroundWorker1.CancelAsync();
}

此外,如果这是相关的,我有:

Also, incase this is relevant, I have:

public delegate void UpdateTextCallback(string item);,这使我可以调用UpdateTextFinishedText,如上backgroundWorker1_DoWork所示.

public delegate void UpdateTextCallback(string item); which allows me to call UpdateText and FinishedText as seen above in backgroundWorker1_DoWork.



对于我的问题,如何在这种情况下使用ExecuteAsync?我已经搜索过,但是找不到任何可以帮助我的东西,找不到与我的代码相似的示例,并且由于我是C#的新手,因此无法将其转换为所需的代码.

同时,我也乐于接受建议,如果您发现我的代码效率低下或没有效率低下,我将很乐意接受您的建议.

谢谢.



For my question, how can I use ExecuteAsync in this context? I have searched but I cannot find anything that will help me, I can't find an example that is similar to my code, and since I'm new to c# I am unable to convert it to what I want.

And also, I am open to suggestions, if you see some inefficiency in my code or what not, I will be happy to accept your suggestions.

Thank you.

推荐答案

这里有两个潜在的问题.

There are a couple of potential problems here.

首先,您似乎正在尝试从后台线程访问UI元素(以及打开MessageBox).这有可能引发CrossThread异常*.

First, you seem to be trying to access a UI element from your background thread (as well open a MessageBox). This has a potential of throwing a CrossThread exception*.

第二,您的代码应更像这样:

Second, your code should look more like this:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    var restClient = new RestClient("http://tumblr.com/api/write");
    foreach (string item in queueBox.Items)
    { 
        //This should be inside the foreach 
        //as it is your loop that will check for cancel. 
        //Your code is procedural once it is in the backgroundworker
        //so it would never return to the spot you had it
        if (backgroundWorker1.CancellationPending)
        {
            e.Cancel = true;
            //MessageBox.Show("You pressed Cancel.");
            //Removed this to the background worker completed method below
            //This avoids any UI cross thread exceptions
            return;
        }
        var request = new RestRequest(Method.POST);
        //I believe Json is default for Restsharp, but you would have to play with it
        request.RequestFormat = DataFormat.Json; //I don't know if this line is necessary
        request.AddParameter("email", usernameBox.Text);
        request.AddParameter("password", passwordBox.Text);
        request.AddParameter("type", "photo");
        request.AddFile("data", FolderName + "\\" + item);
        //If you just pass in item to the below Func, it will be a closure
        //Meaning, any updates in the loop will propogate into the Action
        var newItemToAvoidClosure = item;
        //To use Async, you set up the callback method via a delegate
        //An anonymous method is as good as any here
        restClient.ExecuteAsync(request, 
            response=>
            { 
                //Maybe you should do something with the response?
                //Check the status code maybe?
                doneBox.Invoke(new UpdateTextCallback(this.UpdateText),
                    new object[] { newItemToAvoidClosure });
            }
        );
    }
}

将后台工作人员的RunWorkerCompleted方法与此相关联,并在此处执行所有后处理:

Wire your background worker's RunWorkerCompleted method to this and perform all of your post processing here:

private void backgroundWorker1_RunWorkerCompleted(object sender,
    RunWorkerCompletedEventArgs e)
{
    if(e.Cancelled)
        MessageBox.Show("You pressed Cancel"
}

此外,如果您使用的是4.0+,则建议您查看任务并行库.它可以使您的代码更简洁IMO :).

Also, if you are using 4.0+, then I suggest looking into the Task Parallel Library. It can make your code much cleaner IMO :).

最后,请注意上面的代码,将会发生的情况是,后台工作人员很有可能在所有Rest调用完成之前就返回已完成.这可能会相当快地运行,并且由于无法以这种方式取消(后台工作人员已经完成)而使调用仍然继续进行(但我相信对于每个Rest调用都可以执行此操作).因此,在我看来,真正的问题是取消检查在代码的错误部分(注意,我将其移入了循环,以便可以在处理每个文件之后进行检查).您已经在后台线程中运行,所以在我看来,调用另一个异步是没有意义的(除非您的意图是卸载要发送的数据的循环,然后再卸载实际的发送).

Finally, a note about the above code, what will happen is that the background worker has a high potential to return completed before all of the Rest calls complete. This will probably run fairly quick, and leave the calls still to continue as they are not cancellable in this fashion (the background worker will have already completed)(but I believe there is a way to do this for each Rest call). So, it seems to me that the real problem was that the cancellation check was in the wrong part of the code (notice I moved it inside the loop, so that it can be checked after each file was processed). You are already running in a background thread, so it seems to me that there is no point to calling another async (unless your intent is to offload the looping of the data to be sent, which then offloads the actual sending).

因此,总而言之.我提供了调用异步的方法,但是我认为更大的问题是您没有适当地检查取消调用.

So, in conclusion. I provided the way to call the async, but I believe the bigger problem was that you were not checking for the cancel call appropriately.

*可能不行,因为您仅访问而不是更新UI元素,并且您确实说过这部分正在工作(尽管它可能适用于MessageBox)

*It may not since you are only accessing and not updating the UI element, and you did say this part was working (it probably will for the MessageBox, though)

这篇关于ExecuteAsync RestSharp允许backgroundWorker CancellationPending C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆