Windows Phone 后台任务 - 使用 HttpWebRequest 或 WebClient
我需要使用 WCF 向服务器发送信息。我目前正在使用 WebClient 使用 json 数据调用 WCF。现在,通过后台任务,我使用 json 调用相同的 WCF,但 UploadStringAsync 的回调函数永远不会被调用。我也尝试过 HttpWebRequest,但它也不起作用。
我可以在文档中看到后台任务支持 HttpWebRequest。
下面是处理 WCF 请求/响应的代码:
public class Communication
{
#region Private Variables
/// <summary>
/// Callback method passed to MakeHttpPostRequest will be set to below variable.
/// This variable holds the reference to callback function and used to invoke the method passed by MakeHttpPostRequest calling method.
/// </summary>
private Action<string> action;
private Action<string, object> genericAction;
private object returnValue;
#endregion
#region Methods
/// <summary>
/// Calls WCF service using POST method.
/// </summary>
/// <param name="webserviceURL">URL of WCF service.</param>
/// <param name="json">JSON data to be posted to WCF service.</param>
/// <param name="response">Callback function that is invoked when response is received from WCF service.</param>
public void MakeHttpPostRequest(string webserviceURL, string json, Action<string> response)
{
try
{
this.action = response;
if (DeviceNetworkInformation.IsNetworkAvailable)
{
Uri uri = new Uri(webserviceURL);
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(json);
string data = Encoding.UTF8.GetString(byteArray.ToArray(), 0, (int)byteArray.Length);
WebClient webClient = new WebClient();
webClient.UploadStringCompleted += new UploadStringCompletedEventHandler(this.WebClient_UploadStringCompleted);
webClient.Headers["Content-type"] = "application/json";
webClient.Encoding = Encoding.UTF8;
webClient.UploadStringAsync(uri, "POST", data);
}
else
{
if (this.action != null)
{
this.action(string.Empty);
}
}
}
catch (Exception ex)
{
if (this.action != null)
{
this.action(string.Empty);
}
new ErrorException.ErrorException().HandleError(ex, string.Empty, Global.Modules.General);
}
}
#endregion
#region Events
/// <summary>
/// Callback function that gets called when response is received from web service.
/// </summary>
/// <param name="sender">The object that raises the event.</param>
/// <param name="e">Object containing Http response details.</param>
private void WebClient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
try
{
// Check whether to invoke any method
if (this.action != null)
{
// Invoke the method passed to MakeHttpPostRequest by it's calling method
this.action(e.Result);
}
else if (this.genericAction != null)
{
// Invoke the method passed to MakeHttpPostRequest by it's calling method
this.genericAction(e.Result, this.returnValue);
}
}
catch (Exception ex)
{
if (this.action != null)
{
this.action(string.Empty);
}
new ErrorException.ErrorException().HandleError(ex, string.Empty, Global.Modules.General);
}
}
#endregion
}
并使用下面的代码将 json 发送到服务器:
// Send location data to server
new Common.Communication().MakeHttpPostRequest(Common.ServiceURL.TrackingTracingURL, postData, result);
上面的代码在应用程序中工作正常。但是,从后台任务调用时不起作用。
HttpWebRequest 或 WebClient 没有任何问题。调用时出现问题:
NotifyComplete();
由于 HttpWebRequest 或 WebClient 上的调用是异步的,因此调用 NotifyComplete();在收到响应之前中止后台任务的执行,并且没有等待 HttpWebRequest 或 WebClient 响应。
有人有解决方法吗?
I need to send information to server using WCF. I am currently using WebClient to call WCF with json data. Now, with background task, I am calling the same WCF with json, but the callback function of UploadStringAsync never gets called. I also tried HttpWebRequest, but it is not working too.
I can see in the documentation that HttpWebRequest is supported in Background Tasks.
Below is the code that is handling WCF request/response:
public class Communication
{
#region Private Variables
/// <summary>
/// Callback method passed to MakeHttpPostRequest will be set to below variable.
/// This variable holds the reference to callback function and used to invoke the method passed by MakeHttpPostRequest calling method.
/// </summary>
private Action<string> action;
private Action<string, object> genericAction;
private object returnValue;
#endregion
#region Methods
/// <summary>
/// Calls WCF service using POST method.
/// </summary>
/// <param name="webserviceURL">URL of WCF service.</param>
/// <param name="json">JSON data to be posted to WCF service.</param>
/// <param name="response">Callback function that is invoked when response is received from WCF service.</param>
public void MakeHttpPostRequest(string webserviceURL, string json, Action<string> response)
{
try
{
this.action = response;
if (DeviceNetworkInformation.IsNetworkAvailable)
{
Uri uri = new Uri(webserviceURL);
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(json);
string data = Encoding.UTF8.GetString(byteArray.ToArray(), 0, (int)byteArray.Length);
WebClient webClient = new WebClient();
webClient.UploadStringCompleted += new UploadStringCompletedEventHandler(this.WebClient_UploadStringCompleted);
webClient.Headers["Content-type"] = "application/json";
webClient.Encoding = Encoding.UTF8;
webClient.UploadStringAsync(uri, "POST", data);
}
else
{
if (this.action != null)
{
this.action(string.Empty);
}
}
}
catch (Exception ex)
{
if (this.action != null)
{
this.action(string.Empty);
}
new ErrorException.ErrorException().HandleError(ex, string.Empty, Global.Modules.General);
}
}
#endregion
#region Events
/// <summary>
/// Callback function that gets called when response is received from web service.
/// </summary>
/// <param name="sender">The object that raises the event.</param>
/// <param name="e">Object containing Http response details.</param>
private void WebClient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
try
{
// Check whether to invoke any method
if (this.action != null)
{
// Invoke the method passed to MakeHttpPostRequest by it's calling method
this.action(e.Result);
}
else if (this.genericAction != null)
{
// Invoke the method passed to MakeHttpPostRequest by it's calling method
this.genericAction(e.Result, this.returnValue);
}
}
catch (Exception ex)
{
if (this.action != null)
{
this.action(string.Empty);
}
new ErrorException.ErrorException().HandleError(ex, string.Empty, Global.Modules.General);
}
}
#endregion
}
And using below code to send json to server:
// Send location data to server
new Common.Communication().MakeHttpPostRequest(Common.ServiceURL.TrackingTracingURL, postData, result);
Above code is working fine from application. But, does not work when called from Background Task.
There wasn't any problem with HttpWebRequest or WebClient. It was problem with calling:
NotifyComplete();
As calls on HttpWebRequest or WebClient are async, calling NotifyComplete(); was aborting execution of background task bafore response is received and was not waiting for HttpWebRequest or WebClient response.
Does anybody have workaround for this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
正如 Paul 在评论中提到的,您的后台任务很可能会在 25 秒不活动后被终止。如果您的任务被强制终止 3(?) 次,它将被取消安排,直到您的应用程序再次安排它(我相信如果它持续下去,它们也可能会被永久禁止,但我对此不是 100% 确定)。
Edit
NotifyComplete();
可以发生在异步回调中。处理完响应后,只需将其移至回调末尾即可。As Paul mentioned in his comment, it's likely that your background task is being terminated after 25 seconds of inactivity. If your task is forcefully terminated 3 (?) times it will be unscheduled until your application schedules it again (I believe they can also get perma-banned if it keeps up, but not I'm 100% sure on this).
Edit
NotifyComplete();
can occur in an asynchronous callback. Just move it to the end of your callback, after you've finished processing the response.