Deserialize data from file NOT asynchronously - c#

I just wantend to know if there is a possibility to deserialize data from file NOT asynchronously in WinRT application. It looks like I have to get StorageFile object to deserialize it and getting it must be async. Is that right? Or maybe you know if I can do it synchronously?
This the the async code that works, but it is ASYNC
public static async Task<StorageFile> GetFileFromAsync(string relativeFileName)
{
StorageFolder localAppDataFolder = ApplicationData.Current.LocalFolder;
try
{
StorageFile file = await localAppDataFolder.GetFileAsync(relativeFileName);
return file;
}
catch (FileNotFoundException)
{
return null;
}
}
public static async Task<T> ReadFromXmlInIsAsync<T>(string path) where T : class
{
T data;
StorageFile isolatedStorageFile = await IsolatedStorageHelper.GetFileFromAsync(path);
if(isolatedStorageFile == null) return null;
using (IInputStream sessionInputStream = await isolatedStorageFile.OpenReadAsync())
{
DataContractSerializer sessionSerializer = new DataContractSerializer(typeof(T));
data = (T)sessionSerializer.ReadObject(sessionInputStream.AsStreamForRead());
}
return data;
}

No, there is not a way to do it synchronously.
All WinRT APIs are asynchronous to encourage developers to write responsive applications.

Related

The ReadAsync method cannot be called when another read operation is pending

I have some PDFs stored in my dropbox location and want users to be able to retrieve them via a call to an API.
[HttpGet("{key}")]
public async Task<ActionResult> GetPDF(string key) {
string? path = GetPath(key);
if (path == null) {
return NotFound();
}
using(System.Net.Http.HttpClient wc = new System.Net.Http.HttpClient()) {
try {
using(System.IO.Stream stream = await wc.GetStreamAsync(path)) {
// using(System.IO.Stream stream = wc.GetStreamAsync(path).GetAwaiter().GetResult()) {
return new FileStreamResult(stream, "application/pdf");
}
} catch(System.Exception ex) {
return NotFound();
}
}
}
It runs right through, without hitting the exception, and returns, then gives the error
The ReadAsync method cannot be called when another read operation is pending.
Waiting for the async method didn't help.
Your primary issue appears to be that the stream has been disposed before the function returns. FileStreamResult will dispose the stream, you don't need to do that.
Also, HttpClient should be a global field, otherwise you could get socket exhaustion issues.
HttpClient wc = new HttpClient();
[HttpGet("{key}")]
public async Task<ActionResult> GetPDF(string key)
{
string? path = GetPath(key);
if (path == null)
{
return NotFound();
}
try
{
var stream = await wc.GetStreamAsync(path);
return new FileStreamResult(stream, "application/pdf");
}
catch(System.Exception ex)
{
return NotFound();
}
}

Struggling to get async working on deployment in ASP.net

The code works fine on my development environment, but in deployment with scallable architecture it appears to deadlock.
Objective here is to take a queue of API requests to send to SendGrid, batch them up and process each batch one at a time.
First call from ASHX handler
public void ProcessRequest(HttpContext context)
{
var result = Code.Helpers.Email.Sendgrid.Queue.Process().Result;
if (result.Success)
{
Queue.Process()
public static async Task<GenericMethodResult> Process()
{
var queueItems = GetQueueItemsToProcess();
var batches = BatchQueueItems(queueItems);
foreach (var batch in batches)
{
var r = await batch.SendToSendGrid();
if (r.StopBatch)
{
break;
}
}
return new GenericMethodResult(true);
}
SendToSendGrid()
public async Task<SendGridAPIMethodResponse> SendToSendGrid()
{
var r = new SendGridAPIMethodResponse();
var json = API.Functions.CreateJSONData(this);
var sg = new SendGridClient(Settings.Email.SendgridAPIKey);
dynamic response;
if (Action == Action.UpdateRecipient)
{
response = await sg.RequestAsync(SendGridClient.Method.PATCH, urlPath: "contactdb/recipients", requestBody: json);
}
string jsonResponse = response.Body.ReadAsStringAsync().Result;
// Process response...
return r;
}
I've stripped out as much of the code as I could.
Is anyone able to tell me why this code is timing out in production?
This blocking call to .Result in SendToSendGrid() is causing a deadlock as you are mixing async and blocking calls.
string jsonResponse = response.Body.ReadAsStringAsync().Result;
Use async all the way through
var jsonResponse = await response.Body.ReadAsStringAsync();
and try to avoid mixing blocking calls in async methods.
You should also conside making your handler async as well by using HttpTaskAsyncHandler.
public class MyHandler : HttpTaskAsyncHandler {
public override async Task ProcessRequestAsync(HttpContext context) {
var result = await Code.Helpers.Email.Sendgrid.Queue.Process();
if (result.Success) {
//..other code
}
}
}

Stream is closing when using Async/Await

I have a little service to upload blobs to Azure Storage. I am trying to use it from a WebApi async action, but my AzureFileStorageService says the stream is closed.
I am new to async/await, are there any good resources to help me better understand it?
WebApi Controller
public class ImageController : ApiController
{
private IFileStorageService fileStorageService;
public ImageController(IFileStorageService fileStorageService)
{
this.fileStorageService = fileStorageService;
}
public async Task<IHttpActionResult> Post()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType));
}
await Request.Content.ReadAsMultipartAsync(new MultipartMemoryStreamProvider()).ContinueWith((task) =>
{
foreach (var item in task.Result.Contents)
{
using (var fileStream = item.ReadAsStreamAsync().Result)
{
fileStorageService.Save(#"large/Sam.jpg", fileStream);
}
item.Dispose();
}
});
return Ok();
}
}
AzureFileStorageService
public class AzureFileStorageService : IFileStorageService
{
public async void Save(string path, Stream source)
{
await CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"])
.CreateCloudBlobClient()
.GetContainerReference("images")
.GetBlockBlobReference(path)
.UploadFromStreamAsync(source); // source throws a stream is disposed exception
}
}
You have a problem with your Save() method: you're not returning a Task, and so the calling method has no way to wait for it to finish. That would be fine if you just wanted to fire and forget it, but you can't do that because the stream you pass in is going to be disposed as soon as the Save() method returns (thanks to the using statement).
Instead, you're going to have to either return a Task and await in the calling method, or you're going to have to not have the file stream in a using block, and instead let the Save() method dispose of it when its finished.
One way you could re-write your code would be as follows:
(snippet of calling method):
var result = await Request.Content.ReadAsMultipartAsync(new MultipartMemoryStreamProvider());
foreach (var item in result.Contents)
{
using (var fileStream = await item.ReadAsStreamAsync())
{
await fileStorageService.Save(#"large/Sam.jpg", fileStream);
}
item.Dispose();
}
And the Save method:
public async Task Save(string path, Stream source)
{
await CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"])
.CreateCloudBlobClient()
.GetContainerReference("images")
.GetBlockBlobReference(path)
.UploadFromStreamAsync(source);
}
Checkout this AzureBlobUpload sample we just released a few weeks ago:
The previous answer is definitely a good fix. This is just a complete end to end official sample (perhaps for other folks to get started on).
https://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/AzureBlobsFileUploadSample/ReadMe.txt

Accessing file in windows8 App using C#

This is basically for windows 8 app and I'm writing a file using this method -
static async void WriteDataCords(int numDataCodewords)
{
StorageFolder storageFolder = KnownFolders.DocumentsLibrary;
var storageFile = await storageFolder.GetFileAsync("DataCodeWords.txt");
string data = numDataCodewords.ToString();
await FileIO.AppendTextAsync(storageFile, data);
}
and now I'm reading file using this method -
StorageFolder storageFolder7 = KnownFolders.DocumentsLibrary;
var storageFile7 = await storageFolder6.GetFileAsync("DataCodeWords.txt");
string text7 = await Windows.Storage.FileIO.ReadTextAsync(storageFile7);
but when I run this program it's throwing an error "Access denied or We can't access the file". Using this approach I'm writing many files and reading.Please let me know how to solve this problem.
Thanks in advance
My problem is when I'm accessing file to read and display at that time file is involve in writing process so thats why I'm unable to access that file and it's showing an error.
So. Is there any approach by which we only move forward when the file writing process is complete and than reading process will start?
You could use SemaphoreSlim which limits the number of threads that can access a resource.
Below is an example of a class that handles writing/reading for a file. You create an instance of it when you want to write a file and call the WriteDataCords method. Then you need some way to access the correct instance when you want to read and then call ReadDataCords:
public class FileReadWrite
{
public string FileName { get; set; }
public FileReadWrite(string fileName)
{
FileName = fileName;
}
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
public async Task WriteDataCords(int numDataCodewords)
{
await _semaphore.WaitAsync();
try
{
StorageFolder storageFolder = KnownFolders.DocumentsLibrary;
var storageFile = await storageFolder.GetFileAsync(FileName);
string data = numDataCodewords.ToString();
await FileIO.AppendTextAsync(storageFile, data);
}
finally
{
_semaphore.Release();
}
}
public async Task ReadDataCords()
{
await _semaphore.WaitAsync();
try
{
StorageFolder storageFolder6 = KnownFolders.DocumentsLibrary;
var storageFile7 = await storageFolder6.GetFileAsync(FileName);
string text7 = await Windows.Storage.FileIO.ReadTextAsync(storageFile7);
}
finally
{
_semaphore.Release();
}
}
}
And calling code:
public class ClientCode
{
public async void WriteFile()
{
var fileReadWrite = new FileReadWrite("DataCodeWords.txt");
await fileReadWrite.WriteDataCords(42);
}
public async void ReadFile()
{
var fileReadWrite = GetFileReadWriteForFile("DataCodeWords.txt"); //Method for retreiving correct instance of FileWriteRead class
await fileReadWrite.ReadDataCords();
}
private FileReadWrite GetFileReadWriteForFile(string fileName)
{
}
}
You could skip the FileWriteRead class (it adds complexity) and use SemaphoreSlim directly in the original code for writing/reading but then you could only write/read one file at a time (which might not be a problem).

How can I return a string from an async operation?

I'm using PCLStorage and need a way to read a file. I'm going to use JSON for serialization, so I just need to read the saved content from the file:
public async string ReadFromFile(string filename)
{
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder folder = await rootFolder.CreateFolderAsync("MySubFolder", CreationCollisionOption.OpenIfExists);
IFile file = await folder.GetFileAsync(filename);
string content = await file.ReadAllTextAsync();
return content;
}
But I cant return string, it has to be void, Task or Task.
Is there a easy way I can Return string from this method? maybe by invoking another method?
You need to return a Task<string>, like this:
public async Task<string> ReadFromFile(string filename)
{
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder folder = await rootFolder.CreateFolderAsync("MySubFolder",
CreationCollisionOption.OpenIfExists);
IFile file = await folder.GetFileAsync(filename);
string content = await file.ReadAllTextAsync();
return content;
}

Categories

Resources