ExecuteAsync RestSharp允许backgroundWorker取消挂起c#
我不熟悉C#、RestSharp和线程,所以下面是我要做的:ExecuteAsync RestSharp允许backgroundWorker取消挂起c#,c#,backgroundworker,blocking,kill,restsharp,C#,Backgroundworker,Blocking,Kill,Restsharp,我不熟悉C#、RestSharp和线程,所以下面是我要做的: 我已经做了一个程序,允许我上传照片到tumblr,我已经上传工作到目前为止。现在我需要停止按钮来工作,我相信这意味着我必须使用ExecuteAsync()而不是Execute()。 我还将我的代码放在backgroundworker中,如下所示: private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { if (backgroundWor
我已经做了一个程序,允许我上传照片到tumblr,我已经上传工作到目前为止。现在我需要停止按钮来工作,我相信这意味着我必须使用
ExecuteAsync()
而不是Execute()
。
我还将我的代码放在backgroundworker中,如下所示:
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 });
}
}
}
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 });
}
);
}
}
我相信我的设置是正确的。当我按upload
时,它会相应地转到else
。然而,我认为restreponse response=restClient.Execute(request)代码>这是阻塞,不允许我的代码继续检查标志。
这就是我试图取消它的方式
public void stopButton_Click(object sender, EventArgs e)
{
doneBox.Items.Add("You pressed the stop button.");
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.CancelAsync();
}
此外,如果这是相关的,我有:
public委托void UpdateTextCallback(字符串项)
允许我调用UpdateText
和FinishedText
,如上文backgroundWorker1\u-DoWork
所示
对于我的问题,在这种情况下如何使用ExecuteAsync
?我已经搜索过了,但是我找不到任何对我有帮助的东西,我找不到一个与我的代码类似的示例,而且由于我是c#新手,我无法将它转换为我想要的。
而且,我也乐于接受建议,如果您看到我的代码中存在一些低效或其他问题,我将很乐意接受您的建议。
谢谢。这里有几个潜在的问题
首先,您似乎试图从后台线程访问UI元素(以及打开MessageBox)。这有可能引发交叉线程异常*
其次,您的代码应该更像这样:
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 });
}
}
}
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
方法连接到此方法,并在此处执行所有后期处理:
private void backgroundWorker1_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
if(e.Cancelled)
MessageBox.Show("You pressed Cancel"
}
另外,如果您使用的是4.0+,那么我建议您查看。它可以使您的代码更干净(IMO:)
最后,关于上述代码的一个注意事项是,后台工作程序很有可能在所有剩余调用完成之前返回completed。这可能会运行得相当快,并且让调用继续,因为它们不能以这种方式取消(后台工作人员将已经完成)(但我相信对于每个Rest调用都有一种方法可以做到这一点)。因此,在我看来,真正的问题在于取消检查位于代码的错误部分(注意,我将其移动到循环中,以便在处理每个文件后可以对其进行检查)。您已经在后台线程中运行,因此在我看来,调用另一个异步是没有意义的(除非您的目的是卸载要发送的数据的循环,然后卸载实际的发送)
因此,总结而言。我提供了调用异步的方法,但我相信更大的问题是您没有正确地检查cancel调用
*可能不是这样,因为您只是在访问UI元素,而不是在更新UI元素,而且您确实说过此部分正在工作(不过对于MessageBox可能会工作)谢谢,当我尝试使用此代码时,我得到一个名为response的局部变量不能在此作用域中声明,因为它将赋予“response”不同的含义,而“response”已在“parent”或curren't作用域中用于表示其他内容。
如果我将其更改为“restreponse”\u response=restClient.ExecuteAsync(request,`it删除此错误,但现在我得到无法隐式地将类型RestSharp.RestRequestAsyncHandle'转换为'RestSharp.RestResponse'
@antera我已更新了我的答案,以删除存储异步调用响应的操作(因为这里确实不需要它)。此外,我还建议使用RunWorkerCompleted更好地处理潜在的UI处理错误。最后,您可以将客户端的超时设置为更高的值(我不确定默认值)修复您当前的超时问题。但是,这似乎解决了您最初的问题。如果这是真的,我们将永远感谢您的支持和接受的答案:)谢谢,我感谢您的帮助。我搜索了源代码并通过以下操作使其正常工作:byte[]byteArray=File.ReadAllBytes(FolderName+“\\”+项);
和request.AddFile(“data”,byteArray,FolderName+“\\\”+项);
老实说,我不知道为什么会修复它,但它确实修复了:D.@antera Hrmm,只是看了看代码,它看起来应该可以工作……进一步看:)我猜它可能与StreamReader有关?真有趣。但是,您的工作代码以不同的方式获取数据…这可以解释为什么一个工作,另一个不工作。您在工作开始时看到取消的几率为零。将测试移到循环内。可能已经足够好了。