I am working on new functionality for a large C# project which is mostly legacy code.
The area that I'm working on handles XML schema messages, creates a schedule for their transmission and places them into some legacy timer code which notifies me when they should be sent.
Although I am new to them, Visual Studio test projects are proving useful in that I can test my code without trying to get the full system up and running (which can take upto 30 minutes on the test hardware!).
I have statically tested my event handling code, but would now like to do so dynamically.
Is this possible? If so how do I go about getting the test project to wait for the event without timing out?
If I understand you correctly, you could use a wait handle to signal the event and have your test project wait for the event handle to be signaled.
void Foo()
{
var eventSource = ...;
var waitHandle = new ManualResetEvent(false);
eventSource.SomeEvent += (sender, e) => waitHandle.Set();
...
// Wait for the event to be fired.
waitHandle.WaitOne();
}
Related
I have developed an Xamarin forms application. Provided download option to download file in our application. I have clicked download file and download progress show in app itself. If lock the iphone while download is in progress and unlock it again download stopped. How can I process download even locked phone?. This occurs only in iOS and works properly in Android.
I have used webclient DownloadFileTaskAsync process to download a file and maintain progress value in it.
WebClient client = new WebClient();
client.DownloadFileTaskAsync(new Uri(DownloadUrl), FileName);
Updated Query:
I have implemented the back-grounding process into my source. I have used "Creating Background-Safe Tasks" concept for my download process. I can download more than one file, so put this process in Task itself previously. Now, I have used BeginBackgroundTask in my download process but download process not carried to UI, even BeginBackgroundTask code doesn't hit while debug the code.
Below function put in native and called this function from forms when click download button.
public async Task DownloadFile(string DownloadUrl, string FileName)
{
var taskID = UIApplication.SharedApplication.BeginBackgroundTask(async() =>
{
WebClient client = new WebClient();
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
client.DownloadFileTaskAsync(new Uri(DownloadUrl), FileName);
});
UIApplication.SharedApplication.EndBackgroundTask(taskID);
}
Also registered the app into Background fetch registration categories and now also progress not carried out while lock screen or minimize the app.
Am I missing any process in background techniques? Could you please help me to resolve this or suggest some simple sample as my scenario?
Please help me on this to resolve it.
Regards,
Cheran
You will need to use NSURLSession instead and create a background session for it. You can read how to do this in the official Xamarin Documentation.
You might get away with using WebClient in a background session, but only for a very short time span by using the pattern described in the "Handle iOS Background Limits" docs:
Task.Factory.StartNew(() =>
{
//expirationHandler only called if background time allowed exceeded
var taskId = UIApplication.SharedApplication.BeginBackgroundTask(() => {
Console.WriteLine("Exhausted time");
UIApplication.SharedApplication.EndBackgroundTask(taskId);
});
while(myFlag == true)
{
Console.WriteLine(UIApplication.SharedApplication.TimeRemaining);
myFlag = SomeCalculationNeedsMoreTime();
}
//Only called if loop terminated due to myFlag and not expiration of time
UIApplication.SharedApplication.EndBackgroundTask(taskId);
});
Where you would replace the while with your WebClient code.
However, as mentioned you really need to use Background Transfers for this to work properly.
I have a SignalR hub and two clients (Windows and PCL for Android and iOS). Neither of the clients is able to call some methods on the server. This behaviour is quite odd, since the methods look very similar. Moreover, a colleague of mine is able to call methods I cannot call, and vice versa, does not invoke methods that I invoke with no problems.
Here is an example of a method, which works for me and does not work for my colleague:
public override async Task<bool> RefreshArray(User user, int waitMilis)
{
var cts = new CancellationTokenSource();
try
{
cts.CancelAfter(waitMilis);
await Proxy.Invoke("RefreshArray", user);
return true;
}
catch (Exception ex)
{
OnExceptionOccured(ex);
return false;
}
}
And a method which does not work for me, but works for my colleague:
public override async Task<bool> RequestInformation(User user, Product product, int waitMilis)
{
var cts = new CancellationTokenSource();
try
{
cts.CancelAfter(waitMilis);
await Proxy.Invoke("RequestInformation", user, product);
return true;
}
catch (Exception ex)
{
OnExceptionOccured(ex);
return false;
}
}
Yes, me and my colleague have exactly the same code. And no, there are no typos or different arguments. I have tried to get as much data from the client connection as possible, by setting _connection.TraceLevel = TraceLevels.All; However, I did not get any information on the invoked methods, just on the replies from the hub. When calling RefreshArray, I got exactly the data I requested. When calling RequestInformation, the debugger never even hit the breakpoint in the hub method and the _connection.Trace displayed only this: 11:22:45.6169660 - 7bc57897-489b-49a2-8459-3fcdb8fcf974 - SSE: OnMessage(Data: {})
Has anybody solved a similar issue? Is there a solution?
UPDATE 1
I just realized that I have encountered almost the same issue about a year ago (Possible SignalR bug in Xamarin Android). StackOverflow has also pointed me to a question with almost the same issue (SignalR on Xamarin.iOS - randomly not able to call Hub method), just related to iOS and Azure. However, I got the same proble even outside Xamarin, on Windows Phone 8.1 and and Windows 10 Universal App. Moreover, I am running the server just locally, so it is not an issue od Azure. Is it really possible, that a 2 years old bug has no solution?
UPDATE 2
I have just created a simple console application with SignalR.Client. In the console application every method worked just fine. Amazingly, also the Windows 10 Universal Application started to behave as expected - every hub method was invoked correctly. Windows Phone 8.1 also improved its behaviour (all hub methods invoked). However, every now and then the connection tried to reconnect periodically (for no apparent reason), leading to Connection started reconnecting before invocation result was received. error. The Android application still behaved as before.
So I tried to replicate my previous steps and created another console application, but this time with SignalR.Client.Portable library. To my dissapointment, there was no change in the Android application behaviour.
Next week we will start to test our application on iOS, so I really wonder what new oddities will we encounter.
I have managed to solve the problem (at least so it seems). As it turned out, there is some weird stuff going around, when an application receives an answer from SignalR hub. It seems as if the HubProxy was blocked for a certain period of time on Android, while it drops the connection and starts to reconnect periodically on Windows Phone, not waiting for an asnwer from the hub.
The implementation of RefreshArray on the hub was something like this:
public async Task RefreshArray(User user)
{
await Clients.Caller.SendArray(_globalArray);
await Clients.Caller.SendMoreInformation(_additionalInfo);
}
Because the method sent two methods as an answer, the client Proxy got stuck and each platform handled it in its own unexpected way. The reason why some methods were called on my computer and not on colleagues was, simply, because we had different position of breakpoints, which enabled the application to resolve at least some requests and responses.
The ultimate solution was to add some synchronization into the invokation of methods. Now my hub calls only await Clients.Caller.SendArray(_globalArray);. This is then handled on the client with a ArraySent(string[] array) event, which then subsequently invokes the SendMoreInformation() method on the hub.
I'd like to use a JavaScript library from within a ScheduledTaskAgent on Windows Phone 8. We use this library across our mobile platforms so we don't have to write N versions of it.
I thought I'd be able to do that with a WebBrowser within a ScheduledTaskAgent but I'm running into cross threading issues if I execute this outside of a Dispatcher.BeginInvoke and a System.UnauthorizedAccess exception (claiming I need ID_CAP_WEBBROWSERCOMPONENT despite having that in my application's WMAppManifest.xml) when inside of Dispatcher.BeginInvoke like so:
static ScheduledAgent()
{
// Subscribe to the managed exception handler
Deployment.Current.Dispatcher.BeginInvoke(delegate
{
Application.Current.UnhandledException += UnhandledException;
client = new WebBrowser();
client.NavigateToString("<html><body><script src='https://...path to library...'/></body></html>");
});
}
Has anyone done anything like this before successfully? I can't believe I'm the first person to want to run JavaScript from a background scheduled task on Windows Phone.
As it turns out, the WebBrowser control is not supported in a background task, see: http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202962(v=vs.105).aspx
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
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.