I have a tiny bit of code which in 'normal debug' just hangs executing "var folder =..."
async Task<StorageFolder> GetAssetsFolderAsync()
{
var folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync(#"Assets");
return folder;
}
I placed two breakpoints as in...
If I break at the first I can Debug.StepOver to the line "return folder". If I use debug.Run instead in goes away and doesn't hit the next breakpoint. The method is called from MainPage_Loaded. Any idea how I can correct this problem. And the weirder thin is that it used to work without a problem and I haven't changed THOSE lines.ie lots of others)
After a long long search I found the answer from Mr Skeet and Mr Cleary. I was blocking the UI thread.
It is explained in far greater detail here:
Call to await GetFileAsync() never returns and app hangs in WinRT app
I don't think I would have thought of it. It was fixed with:
public async static Task<bool> StaticInitializeAsync()
{
recordingsFolder = await getRecordingsFolderAsync();
AssetsFolder = await Statics.InstallationFolder.GetFolderAsync(#"Assets");
defaultWavFile = await AssetsFolder.GetFileAsync("Default.wav");
return true;
}
I believe you get an exception which visual studio handles for you silently.
Try opening the exception settings and make sure it brakes on any exception.
Debug -> Windows -> Exception settings
Mark all the CLR exceptions
EDIT:
Also try to catch for AggregateException, these can wrap the true exception when dealing with TPL.
Related
I have an Oracle database that I am accessing through ODP.NET
This is my demo code
public static async Task<Field[][]> ReadAsync(string ExtractSql)
{
var connStr = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
List<Field[]> ret = new List<Field[]>();
using (OracleConnection conn = new OracleConnection(connStr))
{
await conn.OpenAsync();
}
return ret.ToArray();
}
This code does not behave as async, the UI is completely blocked for seconds.
If I simply replace
await Task.Delay(10000); //conn.OpenAsync();
all works fine as expected.
Can I conclude that this is a bug in ODP.NET, is there a github repo or where can I report it or am I missing something trivial in C# async?
Is there anyone else using .NET for Oracle and experiencing a similar issue for async methods?
Please note
Of course I've added the code inside to open the command and read the data and the issue persists, here I'm showing the minimal amount of code that is sufficient to detect the problem. E.g. I have a firewall that can block the connection and in that case it times out, therefore the only "open" command can be enough to make the app stuck, if the db part is not async.
Thank you to #madreflection for the comments. I'm really happy to delete my answer and accept an answer from him, as I kindly asked.
Anyway, now it is clear by looking at Visual Studio intellisense that those async methods are not there but they are symply inherited from the generic System.Data.Common.DbConnection.
I should have also understood it at the first method that is not returning a Task or a Task<bool>, i.e. from the following line
OracleDataReader DR = (OracleDataReader) await cmd.ExecuteReaderAsync();
where I was forced to add an unexpected cast (now I understand why).
I'm going to wrap the API in a Task.Run because I can't block my UI.
See below the screenshot with the mouse over the OpenAsync.
From the doc you can read
This is the asynchronous version of Open(). Providers should override with an appropriate implementation
The default implementation invokes the synchronous Open() call and returns a completed task.
My person opinion is that the default implementation is doing the wrong/misleading thing, I would have rather preferred an exception "not implemented" thrown instead.
I am trying to load a document out of RavenDb via a WebAPI call. When I open an async IDocumentSession and call LoadAsync, I get no exception or result, and the thread exits instantly with no error code.
I was able to bypass all the structure of my API and reproduce the error.
Here is the code that will not work:
public IHttpActionResult GetMyObject(long id)
{
try
{
var session = RavenDbStoreHolderSingleton.Store.OpenAsyncSession();
var myObject= session.LoadAsync<MyObject>("MyObject/1").Result;
return Ok(myObject);
}
catch (Exception e)
{
return InternalServerError(e);
}
}
I simply hard coded the object's Id to 1 for testing, but calling the function for an object that doesn't exist (such as "MyObject/1") has the same result.
However, this code works:
public async Task<IHttpActionResult> GetMyObject(long id)
{
try
{
var session = RavenDbStoreHolderSingleton.Store.OpenAsyncSession();
var myObject= await session.LoadAsync<MyObject>("MyObject/1");
return Ok(myObject);
}
catch (Exception e)
{
return InternalServerError(e);
}
}
Things I tried/fiddled with:
Changing the exceptions that are caught in debugging
Carefully monitoring Raven Studio to see if I could find any problems (I didn't, but I'm not sure I was looking in the right places)
Running the API without the debugger attached to see if the error occurred or if something showed up in Raven Studio (no changes)
So I guess I have stumbled on a "fix", but can someone explain why one of these would fail in such an odd way while the other one would work perfectly fine?
In the real application, the API call did not have the async/await pair, but the code that was making the call was actually using async/await.
Here is the repository class that was failing which caused me to look into this issue:
public async Task<MyObject> Load(string id)
{
return await _session.LoadAsync<MyObject>(id);
}
The first part that is failing is as per design, for ASP.Net async call, you are blocking the Synchronization context, when you call the Result on a Task returned and same Synchronization context is required for call to return the data. Check out the following link by Stephen Cleary, where the same mechanism is explained in detail.
Second part works since that is correct way of using it and it's not getting into the deadlock anymore. First part can only work if you are using the Console application, which doesn't have a synchronization context to block, even other UI like winforms will have a similar issue and need to use the use the Second part of the code
I have founds threads similar but not the same so forgive me if it turns out to be a duplicate. How does one properly "throw" an error inside a task. I have this code and when the conditions are right it will throw the error but Visual Studio complains that it is unhanded. But afterwards everything performs as it should including the _LoadDataMappingFieldListError method. I thought the first ContinueWith would suffice but it seems not. Do I need to actually create 2 separate tasks - one for the test and then another for the actual retrieval? Seems a little redundant. Here is the code:
........
if (dcMapping.SettingsComplete().IsNullEmpty())
{
_TaskCanceller = new CancellationTokenSource();
_TaskLoader = Task<object>.Factory.StartNew(() =>
{
//Set the indicator and first test the connection to make sure it is working
IsLoadingDataMappingFieldList = true;
string test = dcMapping.TestConnection();
if (test.IsNotNullEmpty())
throw new DataConnectionException(test); // <--THE THROW IN QUESTION
return dcMapping.GetFieldNameList(); // <--VS BREAKS HERE SAYING THE ABOVE IS UNHANDLED
});
//If there is an error
_TaskLoader.ContinueWith(
antecendant => _LoadDataMappingFieldListError(antecendant.Exception),
_TaskCanceller.Token,
TaskContinuationOptions.OnlyOnFaulted,
TaskScheduler.FromCurrentSynchronizationContext());
//Set up receiving function
_TaskLoader.ContinueWith(
antecendant => _LoadDataMappingFieldListComplete((List<string>)antecendant.Result, RemapFields),
_TaskCanceller.Token,
TaskContinuationOptions.NotOnFaulted,
TaskScheduler.FromCurrentSynchronizationContext());
}
........
You most likely have the option "Just my code" turned on. In that case, it is indicating that the exception is unhandled with respect to "just your code". The exception is caught by framework code and stored in the Task.
I, personally, would recommend turning off the "Just my code" setting as it tends to get in the way more than it helps.
I am having trouble with a demo from msdn
The demo
On the method updateUserName:
public static async Task updateUserName(TextBlock userName, Boolean signIn)
{
try
{
// Open Live Connect SDK client.
LiveAuthClient LCAuth = new LiveAuthClient();
LiveLoginResult LCLoginResult = await LCAuth.InitializeAsync();
try
{
//this is never reached
LiveLoginResult loginResult = null;
if (signIn)
......
the code hangs at ht InitialuzeAsync() method and never enters the try statement. Can someone who has used the live SDK please tell me what migh be wrong? The code is a direct copy-paste from the demo and the live SDK was installed via NuGet on VS2012.
I predict that you are calling Task.Wait or Task<T>.Result somewhere further up your call stack. As I describe on my blog, you are causing a deadlock because the await is attempting to resume on the UI thread.
The correct solution is to use await "all the way", which is one of the best practices I describe in my article. If you have a situation where you think you "can't" use await, then take a look at my async/OOP blog series, which describes various code patterns for async code, most notably constructors and properties.
Seems you have to associate your app with the store to use this feature, or else it hangs. After associating it, everything started working.
First of all I am stumped. I have a search-module for a CMS that runs fine on one site, but it won't run as it's supposed to on another site.
I have this code I call both with an Ajax call and simply when loading the search site:
private string GetSearchContent()
{
Query q = GetQuery();
//for each area, set it up, perform search and render result
IArea products = new ProductArea(GetEcomExcludedGroupIDs(), GetEcomLanguage()).Search(q);
IArea pages = new PageArea(GetAreaId())
.Search(q);
IArea news = new NewsArea(GetIncludedNewsCategoryIDs())
.Search(q);
....
}
The important part here is the Search function. This is implemented in the classes, but for some reason the code won't be executed.
I have tried splitting the code up so I am sure that is where the error lies. The freaky part is that it does not throw any exceptions, but it just stops executing whenever I try to call the Search function. It doesn't even enter the function.
The Search function looks like this:
public override IArea Search(Query q)
{
log.Debug("Product search");
....
}
The function it overrides is simply an abstract function on an interface that declares the function.
I have tried copying the function to the same class that are executing it with no luck, and I have tried accessing other functions on the classes, and that worked fine.
My question is then. What could cause this behavior? I have tried looking around but couldn't really find any others with the same problem. And as mentioned before, the exact same code is running smoothly on another site.
I really hope someone can help me get closer to a fix, or at least to understand the problem.
The question is unanswerable as written. You assert that the Search method never runs, and that the faulty line is this one:
IArea news = new NewsArea(GetIncludedNewsCategoryIDs()).Search(q);
There are a few different things that could be wrong outside of the Search method:
The NewsArea constructor throws an exception
The GetIncludedNewsCategoryIDs method throws an exception
Either of the above could call into unmanaged code and generate a native Win32 exception, which under some circumstances will simple cause the process to terminate rather than ever returning to managed code.
You state that "there is no try-catch" -- all the more reason to disbelieve your assertion that the method just stops without throwing an exception. Try the following for diagnostic purposes:
try
{
IArea news = new NewsArea(GetIncludedNewsCategoryIDs()).Search(q);
}
catch (Exception e)
{
Logger.Log("Caught in the act: " + e.ToString());
throw;
}
If you've run this and still see that the execution stops without logging any exception, then we'll look at other possibilities.