How to make a synchronous web call from within a background agent - windows-phone-7

I am fairly new to wp7 development, and currently developing an app that has a background agent to update values based upon responses it gets from a web call to an api.
My problem is that the response to the web call is an asynchronous call and I can not access the results returned from within the background agent.
Is there any way that i can make a synchronous call from within the background agent so as to allow me to deal with the results within the same agent?
I have tried dealing with the web call within a class in a shared library but the Asynchronous call is only made after the onInvoke method of the agent has finished and so no use. Any Ideas would be great.

You simply need to call the NotifyComplete() method in your async call's Completed handler, and not before. Remove the call at the end of Invoke.

you could use an AutoResetEvent like this:
protected override void OnInvoke(ScheduledTask task)
{
AutoResetEvent are = new AutoResetEvent(false);
//your asynchronous call, for example:
WebClient wc = new WebClient();
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
wc.OpenReadAsync(searchUri, channel);
// lock the thread until web call is completed
are.WaitOne();
//finally call the NotifyComplete method to end the background agent
NotifyComplete();
}
and your callback method should look like:
void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
//do stuff with the web call response
//signals locked thread that can now proceed
are.Set();
}
remember that you should check if a connection is available and handle possible exceptions, if your background agent gets killed twice consecutively (due to memory consumed or duration) it will be disabled by the OS.

Related

Calling internal (Endpoint) function in WebAPI

I am using Hangfire to execute recurring jobs in my web API and I use System.Web.HttpContext.Current.Server.MapPath in the "RoutineMethod" function.
But the problem is it throws object null exception.
I searched the problem and found that recurring jobs don't use http threads, they use background threads.
Now to resolve this problem I need to call my internal (endpoint) using httpclient.
But to do that I need to give URL of the Web API (to generate URI). So is there any other way to call internal function using httpclient.
My current code:
public static async Task<IHttpActionResult> RoutineTask()
{
//It was like this before.
//await new DemoController().RoutineMethod();
//await new DemoController().RoutineMethod2();
//I am planning to do this.
using (var client = new HttpClient())
{
//But I need to give URI which I don't think is a good idea.
var uri = new Uri("http://localhost/DemoApp/api/DemoController/RoutineMethod");
await client.GetAsync(uri);
}
return new DemoController().Ok();
}
The short answer is no. The HttpClient, as its name implies, requires an http connection.
There are no smell issues with storing service connection information in a configuration file.
However, to expand on Nkosi's comment, it appears that since your code can create an instance of DemoController, that it must have a reference to that controller's project or even be in the same project. I would extract the interesting code into a library or service that all areas needing the information can reference.

session state service failed prism (Windows store app)

I am trying to react to suspend events within my Windows Store App. I added the appropriate callback method, but I've run into a problem:
App.Current.Suspending += Current_Suspending;
void Current_Suspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e){}
The problem is that, when I trigger the suspension event in Visual Studio and the callback method is called (I have checked it with a breakpoint), it immediately terminates with an Exception:
session state service failed.
Any suggestions on how to solve this problem?
If you are using Prism as I was this can happen when the SessionStateService chokes on serializing an object. Relevant navigation parameters and anything manually added get serialized at app termination or suspension. In my specific case i had a non-nullable enum that wasn't being set on an object used as a navigation parameter. I used the following to verify the DataContractSerializer wasn't having issues with object.
test.Add("testitem", new WorkflowStep());
MemoryStream sessionData = new MemoryStream();
DataContractSerializer serializer = new DataContractSerializer(typeof(Dictionary<string, object>));
serializer.WriteObject(sessionData, test);

Starting a WCF service in Windows Service when initialization takes a long time

I have a WCF project that I host in a windows Service (actually I use topshelf) and it runs fine. I have to make changes however that will cause the initialization to take substantially longer. This causes problems when the service starts as it times out while executing the WCF Service constructor.
I wanted to reduce the amount of code in the constructor and then when the service was opened I would do my longer running initializations. I put register the open event in the WCF ctor but it does not seem to be called.
public WCFService()
{
this.Faulted += WCF_Faulted;
this.Opened += WCF_Opened;
...
and event handlers
void WCF_Opened(object sender, EventArgs e)
{
}
void WCF_Faulted(object sender, EventArgs e)
{
}
I am guessing that I am not implementing this correctly.
I was able to trap the opened event in the servicehost but then I dont know how to access the instance (it is a singleton) to call a method on it.
Ideas?

Azure CloudBlockBlob.DownloadTextAsync() in asp.net Web API project never returns but same works in console application

I've created one Asp.Net Web API project which uses Azure CloudBlockBlob to download some text asynchronous, but the call never returns.
I tried to run the same code in Console App and it works fine.
Following is the code which has issue:-
public async Task<string> DownloadTextAsync(IBlobRef blobRef, CancellationToken cancellationToken)
{
var container = this.GetContainerReference(blobRef);
try
{
this.Logger.Log("Downloading " + blobRef.BlobName);
return await container.GetBlockBlobReference(blobRef.BlobName).DownloadTextAsync();
}
catch (Microsoft.WindowsAzure.Storage.StorageException e)
{
if (e.RequestInformation.HttpStatusCode == 404)
return null;
Console.WriteLine("Error reading " + blobRef.BlobName + " " + e.Message);
return null;
}
}
This same code if I run in console application or asp.net web form application then it runs perfectly fine.
Kindly help if I'm doing anything wrong.
You're almost certainly calling Task<T>.Result or Task.Wait further up your call stack. This causes a common deadlock issue that I describe on my blog.
The reason it deadlocks is because await (by default) will capture the current "context" - in this case, an ASP.NET request context. Then, when the operation completes, it will resume the async method within that context. However, the ASP.NET request context will only allow one thread in at a time. So, if there's a thread blocked in the ASP.NET request context (e.g., by calling Task.Wait), then the async method cannot resume executing when the await completes.
It doesn't deadlock in a Console app because Console apps do not have a "context". In this case, the async method resumes on a thread pool thread.
To resolve this issue, replace any calls to Result or Wait with await, and allow async to grow through your code. For more information, see my MSDN article on async best practices.

Background worker blocking UI when using web service call

For some reason when i put a long running web service call (doesn't matter if its a legacy one or WCF) in a background thread it seems to be locking up the UI main thread.
I cant see anything wrong with the code im putting in.
workerThreadInitialNotify = new BackgroundWorker();
workerThreadInitialNotify.WorkerSupportsCancellation = true;
workerThreadInitialNotify.DoWork += new DoWorkEventHandler(workerThreadInitialNotify_DoWork);
workerThreadInitialNotify.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workerThreadInitialNotify_RunWorkerCompleted);
workerThreadInitialNotify.RunWorkerAsync();
Then in my do work i have a webservice call like:
void workerThreadInitialNotify_DoWork(object sender, DoWorkEventArgs e)
{
if (!(sender as BackgroundWorker).CancellationPending)
{
try
{
TestWebService service = new TestWebService();
service.RunLongRunningMethod();
}
catch(Exception ex)
{
}
}
}
When this thread is called, it occasionally locks up the UI thread, now i have setup the RunLongRunningMethod to purposely run slow and timeout (for testing purposes), but technically this shouldn't lockup the UI thread at all as its in a seperate thread.
Here is what the method contains:
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["customConnection"].ConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("TestDelay", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
try
{
cmd.ExecuteNonQuery();
}
catch (Exception ee)
{
}
}
}
and TestDelay stored proc just contains this to simulate a delay so that the web service times out:
ALTER PROCEDURE [dbo].[TestDelay]
AS
WAITFOR DELAY '00:05:20';
The strange thing is that if i replace the web service call with a Thread.Sleep(20000); in the dowork, it runs perfectly, or even if i put a long running while loop it runs perfectly also.
I have no idea why specifically the webservice makes it lock up the UI.
ps: if i set up the webservice to be hosted locally to the Win Forms app, it runs ok, only when the webservice is running on another service, the strange lockup occurs.
ps (2): i am using devexpress library for ui controls of forms while the background thread runs in the background, not sure if this is related. I cant imagine why, if this is run in a seperate thread correctly
This ended up being a maxconnection .net setting in the App.config (its defaulted to a very low 2 by microsoft)
<system.net>
<connectionManagement>
<add address="*" maxconnection="40"/>
</connectionManagement>
</system.net>
Its now set to 40 and the issue has gone away.
There was multiple threads running at the same time, each calling web services, each of them were blocking each other.
There is more information in these links:
http://blogs.msdn.com/b/adarshk/archive/2005/01/02/345411.aspx
What is limiting the # of simultaneous connections my ASP.NET application can make to a web service?
http://msdn.microsoft.com/en-us/library/fb6y0fyc.aspx

Resources