Accessing task contents from await - c#

I have a method that returns Task< PixelData >.
myObject.pixelData = await rootPage.GrabPixelData("mypic.png");
I have confirmed (from the debugger) that the method completes (and returns a non-null value), but when execution returns myObject.pixelData remains null.
Stangely, the line immediately after that point is never hit (a breakpoint I set there never stops execution).
Here is the class:
public class PixelData
{
public byte[] sourcePixels;
public int sizeOfSourcePixels;
public int imageWidth;
public int imageHeight;
}
Here is the method that gets called:
public async Task<PixelData> GrabPixelData(string imageFileName)
{
if (!ImageDictionary.ContainsKey(imageFileName))
{
// doesn't exist yet, so load it
PixelData pd = await LoadPic(imageFileName);
ImageDictionary.Add(imageFileName, pd);
}
var test = ImageDictionary[imageFileName];
return ImageDictionary[imageFileName];
}
I'm pretty new to async / await, and I can't seem to figure this one out.
Do I need to inherit from a certain interface in the PixelData class? Do I need to cast the result to another type? Why doesn't the very next line ever get executed?

I strongly suspect the cause is some hidden, arcane aspect of .NET 4.5 or it's a bug.
Anyway, the workaround for me was to make an asynchronous call to load the file into the parent class and then grab it in the next line.
Something like this:
await rootPage.LoadPixelData("mypic.png");
myobject.pixelData = rootPage.ImageDictionary["mypic.png"];
loadedFlag = true;
Is my layout of the classes a little strongly typed? Yes. That's because XAML wipes out my class every time I switch pages, so I have to store everything in the parent class to avoid reloading.

Related

C# object reference is required for the non-static field, method, or property

I've been looking up static methods and non-static properties but I don't understand how it applies here. It's been a while since I've looked at C# code. I get the following error message from the following code. Any help would be greatly appreciated.
(awaitable) Task >
IgRestApiClient.createPositionV2(CreatePositionRequest createPositionRequest)
Creates an OTC position #param createPositionRequest the request for creating a position #return OTC create position response
An object reference is required for the non-static field, method, or property 'IgRestApiClient.createPositionV2 (CreatePositionRequest)'
public async void BuyThis()
{
try
{
var buyDataX = new CreatePositionRequest
{
epic = "THIS",
expiry = "MAY-20",
direction = "SELL",
size = 1,
level = 100,
orderType = "LIMIT",
guaranteedStop = false,
stopLevel = null,
stopDistance = null,
trailingStop = false,
trailingStopIncrement = null,
forceOpen = false,
limitLevel = null,
limitDistance = null,
quoteId = null,
currencyCode = "USD",
timeInForce = "EXECUTE_AND_ELIMINATE",
};
var response = await IgRestApiClient.createPositionV2(buyDataX);
}
catch (Exception ex)
{
}
}
public async Task<IgResponse<CreatePositionResponse>> createPositionV2(dto.endpoint.positions.create.otc.v2.CreatePositionRequest createPositionRequest)
{
return await _igRestService.RestfulService<CreatePositionResponse>("/gateway/deal/positions/otc", HttpMethod.Post, "2", _conversationContext, createPositionRequest);
}
var response = await IgRestApiClient.createPositionV2(buyDataX);
IgRestApiClient is not an object, but a class definition, so it's telling you that you are trying to use a non static method as if it was static.
Initiate the IgRestApiClient with new IgRestApiClient(), and then use that object to call the createPositionV2.
You've got this non static class:
public class IgRestApiClient{
public async Task<IgResponse<CreatePositionResponse>> createPositionV2(CreatePositionRequest createPositionRequest)
{
return await _igRestService.RestfulService<CreatePositionResponse>("/gateway/deal/positions/otc", HttpMethod.Post, "2", _conversationContext, createPositionRequest);
}
}
You're trying to use it statically:
var response = await IgRestApiClient.createPositionV2(buyDataX);
You either need this (make class static):
public static class IgRestApiClient{
Or this (create an instance first):
var x = new IgRestApiClient();
var response = await x.createPositionV2(buyDataX);
Which one to pick? Well.. whichever one is used elsewhere. If this is the only use, I guess you need to decide based on how IgRestApiClient looks like its lifecycle should behave. Perhaps it reuses something properly and hence looks like it should be single instance, or perhaps it disposes something after a single use and hence relies on being renewed every time it is to be used. (I get the feeling this isn't your code originally that you're maintaining)
Incidentally, the method signature will get simpler if you using dto.endpoint.positions.create.otc.v2, if you didn't already- then you can just refer to CreatePositionRequest
Also, you may be able to declare this method like:
public Task<IgResponse<CreatePositionResponse>> createPositionV2Async(CreatePositionRequest createPositionRequest)
{
return _igRestService.RestfulService<CreatePositionResponse>("/gateway/deal/positions/otc", HttpMethod.Post, "2", _conversationContext, createPositionRequest);
}
}
There may be no need to use async/await here because the method doesn't do anything other than make a call and get a task and pass it on. This doesn't mean it's no longer async in the way it behaves; it returns a task, it's asynchronous, and I've renamed it to highlight this, but if you have methods that don't do anything with tasks other than return await them then you may be able to just return the Task that the other method created and let the calling method await it just the same.
Take a read of What is the purpose of "return await" in C#? for some interesting discussion around the concept
You need to initialize a object & then only can call the methods of non static class. As I can see IgRestApiClientis not not staticso you need to initialise an instance of class before calling it.
IgRestApiClient _igRestApiClient = new IgRestApiClient();
Then you can call it like
var response = await _igRestApiClient.createPositionV2(buyDataX);
for better solution with dependency injection you can do it like :
public partial class IgRestApiClient
{
private PropertyEventDispatcher eventDispatcher;
private ConversationContext _conversationContext;
private IgRestService _igRestService;
public IgRestApiClient(string environment, PropertyEventDispatcher eventDispatcher)
{
this.eventDispatcher = eventDispatcher;
this._igRestService = new IgRestService(eventDispatcher, environment);
}
///<Summary>
///Creates an OTC position
///#param createPositionRequest the request for creating a position
///#return OTC create position response
///</Summary>
public async Task<IgResponse<CreatePositionResponse>> createPositionV2(dto.endpoint.positions.create.otc.v2.CreatePositionRequest createPositionRequest)
{
return await _igRestService.RestfulService<CreatePositionResponse>("/gateway/deal/positions/otc", HttpMethod.Post, "2", _conversationContext, createPositionRequest);
}
For reference :
https://github.com/IG-Group/ig-webapi-dotnet-sample/blob/master/IGWebApiClient/IGRestApiClient.cs
https://csharp.hotexamples.com/site/file?hash=0x52fbb58774cf38505f1f8d4da108670fffda8578a1b7dcb434a671907f5ddaab&fullName=IGApi/IGApiClientApplication.cs&project=JBetser/MiDax

List<MyClass> from awaitable task

In my application, different canvases are stored as "pages", the contents of each canvas is stored as "cells".
Now when I want to load all cells that occupy / make up one canvas, I retrieve them like this:
public Task<List<Cell>> GetCellsAsync(string uPageGUID)
{
return database.QueryAsync<Cell>("SELECT * FROM cells WHERE cellpageguid = ?", uPageGUID);
}
This works great.
Now I would like to find out the "pageguid" of the page that has the value "pageisstartpage" set to true.
Therefore I'm trying the following:
public Task<string>GetStartPageGUID()
{
nPages<List<Page>>=database.QueryAsync<Page>("SELECT * FROM pages WHERE pageisstartpage=?", true);
return nPages.First.GUID;
}
The compiler tells me:
nPages doesn't exist in the current context.
I don't see where I made a mistake.
nPages doesn't exist in the current context....I don't see where I made a mistake.
The first thing to mention is that the declaration of the List<Page> seems backwards.
nPages<List<Page>>=database....
The type has to be written first followed by the variable name.
List<Page> nPagesTask = database...
Another interpretation could be that you have a generic type variable nPages in which you want to specify the generic type. So the compiler looks whether this variable has already been declared. And apparently it cannot find any.
The second thing If you have an async method that returns a Task<string> you could do the following:
public async Task<string>GetStartPageGUID()
{
Task<List<Page>> nPagesTask = database.QueryAsync<Page>("SELECT * FROM pages WHERE pageisstartpage=?", true);
List<Page> npages = await nPagesTask;
return nPages.First().GUID;
}
Here is the source of the QueryAsync method. this is the signature:
public Task<List<T>> QueryAsync<T> (string query, params object[] args)
so it returns a Task<List<T>>. Since your method specifies a different return type the usual pattern is to await it in a async method as described in the MSDN example and then return the type that you specified in you method.
You have to declare nPages correctly:
List<Page> nPages = database.QueryAsync<Page>("SELECT * FROM pages WHERE pageisstartpage=?", true);

Roslyn Code Action: How to check if preview or real execution?

I am currently experimenting with Roslyn and Code Actions, more specific Code Refactorings.
It feels kind of easy, but I have a difficulty I cannot solve.
Code actions are executed once against a dummy workspace as a "preview" option, so that you can see the actual changes before you click the action and execute it against the real workspace.
Now I am dealing with some things Roslyn can't really do (yet), so I am doing some changes via EnvDTE. I know, it's bad, but I couldn't find another way.
So the issue here is:
When I hover over my code action, the code gets executed as preview, and it should NOT do the EnvDTE changes. Those should only be done when the real execute happens.
I have created a gist with a small example of my code. It doesn't really makes sense, but should show what I want to achieve. Do some modifications via roslyn, then do something via EnvDTE, like changing Cursor position. But of course only on the real execution.
The relevant part for those who can't click the gist:
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(continueOnCapturedContext: false);
var node = root.FindNode(context.Span);
var dec = node as MethodDeclarationSyntax;
if (dec == null)
return;
context.RegisterRefactoring(CodeAction.Create("MyAction", c => DoMyAction(context.Document, dec, c)));
}
private static async Task<Solution> DoMyAction(Document document, MethodDeclarationSyntax method, CancellationToken cancellationToken)
{
var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken);
var root = await syntaxTree.GetRootAsync(cancellationToken);
// some - for the question irrelevant - roslyn changes, like:
document = document.WithSyntaxRoot(root.ReplaceNode(method, method.WithIdentifier(SyntaxFactory.ParseToken(method.Identifier.Text + "Suffix"))));
// now the DTE magic
var preview = false; // <--- TODO: How to check if I am in preview here?
if (!preview)
{
var requestedItem = DTE.Solution.FindProjectItem(document.FilePath);
var window = requestedItem.Open(Constants.vsViewKindCode);
window.Activate();
var position = method.Identifier.GetLocation().GetLineSpan().EndLinePosition;
var textSelection = (TextSelection) window.Document.Selection;
textSelection.MoveTo(position.Line, position.Character);
}
return document.Project.Solution;
}
You can choose to override ComputePreviewOperationsAsync to have different behavior for Previews from regular code.
I've found the solution to my problem by digging deeper and trial and error after Keven Pilch's answer. He bumped me in the right direction.
The solution was to override both the ComputePreviewOperationsAsync and the GetChangedSolutionAsync methods in my own CodeAction.
Here the relevant part of my CustomCodeAction, or full gist here.
private readonly Func<CancellationToken, bool, Task<Solution>> _createChangedSolution;
protected override async Task<IEnumerable<CodeActionOperation>> ComputePreviewOperationsAsync(CancellationToken cancellationToken)
{
const bool isPreview = true;
// Content copied from http://sourceroslyn.io/#Microsoft.CodeAnalysis.Workspaces/CodeActions/CodeAction.cs,81b0a0866b894b0e,references
var changedSolution = await GetChangedSolutionWithPreviewAsync(cancellationToken, isPreview).ConfigureAwait(false);
if (changedSolution == null)
return null;
return new CodeActionOperation[] { new ApplyChangesOperation(changedSolution) };
}
protected override Task<Solution> GetChangedSolutionAsync(CancellationToken cancellationToken)
{
const bool isPreview = false;
return GetChangedSolutionWithPreviewAsync(cancellationToken, isPreview);
}
protected virtual Task<Solution> GetChangedSolutionWithPreviewAsync(CancellationToken cancellationToken, bool isPreview)
{
return _createChangedSolution(cancellationToken, isPreview);
}
The code to create the action stays quite similar, except the bool is added and I can check against it then:
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
{
// [...]
context.RegisterRefactoring(CustomCodeAction.Create("MyAction",
(c, isPreview) => DoMyAction(context.Document, dec, c, isPreview)));
}
private static async Task<Solution> DoMyAction(Document document, MethodDeclarationSyntax method, CancellationToken cancellationToken, bool isPreview)
{
// some - for the question irrelevant - roslyn changes, like:
// [...]
// now the DTE magic
if (!isPreview)
{
// [...]
}
return document.Project.Solution;
}
Why those two?
The ComputePreviewOperationsAsync calls the the normal ComputeOperationsAsync, which internally calls ComputeOperationsAsync. This computation executes GetChangedSolutionAsync. So both ways - preview and not - end up at GetChangedSolutionAsync. That's what I actually want, calling the same code, getting a very similar solution, but giving a bool flag if it is preview or not too.
So I've written my own GetChangedSolutionWithPreviewAsync which I use instead. I have overriden the default GetChangedSolutionAsync using my custom Get function, and then ComputePreviewOperationsAsync with a fully customized body. Instead of calling ComputeOperationsAsync, which the default one does, I've copied the code of that function, and modified it to use my GetChangedSolutionWithPreviewAsync instead.
Sounds rather complicated in written from, but I guess the code above should explain it quite well.
Hope this helps other people.

How to get access to application context from the thread that was created via Task.Factory.StartNew

I have a method that is ran in the main application thread, but creates new Task for long-running operation and awaits it's result.
public async Task<CalculatorOutputModel> CalculateXml(CalculatorInputModel input)
{
// 1
return await Task.Factory.StartNew(
new Func<CalculatorOutputModel> (() =>
{
// 2
using (var ms = Serializer.Serialize(input))
{
ms.Position = 0;
using (var rawResult = Channel.RawGetFrbXmlOutputs(ms)) // 3
{
var result = Parser.Parse(rawResult);
return result;
}
}
}),
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
}
My problem is that the AppContext in points (1) and (2) are "a bit" different. In point 1 there is usual application context in Current property, that has all the data I need. In point 2, as you understand, there is null reference in AppContext.Current, so I can't access any data. The problem with accessing context in point 2 seems to be easy, just "catch" current context in local variable or pass it as the parameter. The problem for me is more difficult because I need to access the context somewhere in the deep of line marked as "3".
The class itself is derived from System.ServiceModel.ClientBase<TChannel> and the place where I need to get access to the context is the class that implements IClientMessageInspector.
class CalculatorMessageInspector : IClientMessageInspector
{
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
if (AppContext.Current != null)
{
// never goes here
}
}
}
Just to clarify, here is the call stack (I can't pass my context inside required method):
So:
I can't pass context to Channel's method because it does not make any sense;
I can't save required parameters from context in Channel because it is proxy class;
I can't save required parameters in CalculatorMessageInspector because it is created within the place where current context is already null.
Can anyone advise any method how can I stay within the same context in another thread? Or, at least, how can I pass parameter from the place marked "2" inside the methods hierarchy? Maybe, I can use SynchronizationContext somehow to achieve it? Thanks a lot for any suggestions.
Update
AppContext.Current consider to be the same as HttpContext.Current != null ? HttpContext.Current.Items[AppContextKey] : null
Update 2
So it seems, that in this case there is no common solution to persist the context. Hence, the only applicable solution in this concrete situation (that is quite specific) is to capture required parameters using closure and save then in an object, that will be available in required method (for me worked adding properties to the implementator of IEndpointBehavior, but that solution is a bit odd). Thereby, the most applicable solution is to throw away the asynchronous wrapping over the sync call, so the AppContext never "goes away". Mark Stephen's answer as the right then.
To use async and await on ASP.NET, you must target .NET 4.5 and turn off quirks mode. The best way to do this is to set /configuration/system.web/httpRuntime#targetFramework="4.5" in your web.config.
Also, you shouldn't use Task.Run or Task.Factory.StartNew on ASP.NET. So your code should look more like this:
public CalculatorOutputModel CalculateXml(CalculatorInputModel input)
{
using (var ms = Serializer.Serialize(input))
{
ms.Position = 0;
using (var rawResult = Channel.RawGetFrbXmlOutputs(ms))
{
var result = Parser.Parse(rawResult);
return result;
}
}
}

Windows 8 Store App and Linq

The snippet below is from a Windows 8 store app in c# and xaml.
I have put this code together from variou samples on the web so this may not be the neatest way of doing this. Most of it is from the Grid template supplied in VS2012 and I have hooked up my web api as the source of the data
Please explain the following
When i call the Get method all works fine and i get data back into the xaml view
When i uncomment the Take(10) in the same method i get no data back.
It seems any attempt to put an extension method of a LINQ variety just stops the data being returned and also gives no indication why, it complies fine!
Any help appreciated
Thanks
Mark
public class TeamDataSource
{
private static TeamDataSource _sampleDataSource = new TeamDataSource();
private ObservableCollection<TeamDataItem> _items = new ObservableCollection<TeamDataItem>();
public ObservableCollection<TeamDataItem> Items
{
get { return this._items; }
}
public TeamDataSource()
{
this.Initialize();
}
public static IEnumerable<TeamDataItem> Get()
{
var thisdata = _sampleDataSource.Items;
return thisdata;//.Take(10);
}
private async void Initialize()
{
using (var client = new DataServiceClient())
{
List<TeamDataItem> list = await client.Download<List<TeamDataItem>>("/teams");
foreach (var i in list.OrderByDescending(t => t.Points).ThenByDescending(t => t.GoalDiff))
{
TeamDataItem team = i;
_items.Add(team);
}
}
}
}
Your problem is that Take doesn't immediately enumerate the items. It defers enumeration until either foreach is called on it or GetEnumerator is called on it. In this case the collection it is enumerating is disposed (as soon as the Get content ends) and so when it finally enumerates the items, there are no items anymore. Try adding thisdata.GetEnumerator(); as a line before your return statement.
From here:
This method is implemented by using deferred execution. The immediate
return value is an object that stores all the information that is
required to perform the action. The query represented by this method
is not executed until the object is enumerated either by calling its
GetEnumerator method directly or by using foreach in Visual C# or For
Each in Visual Basic.
Seems it was quite obvious in the end. As I was using aync and await, the call was immediately returning before the data had arrived. Therefore nothing for the Take(4) to work on.
Only problem now is when can i tell the task has completed?

Categories