I am looking to use Microsoft.Azure.WebJobs.ExecutionContext to get the InvocationId while a function is running, but is there a way to get this while outside of the actual function call.
So if a calling class needs to have some kind of context it can use this. Is it possible?
When you run a function you have ExecutionContext
public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log, ExecutionContext context)
{
return req.CreateResponse(System.Net.HttpStatusCode.OK, context.InvocationId);
}
So if you call any method you probably will need to path this id to it. I am not sure if there is any kind of static helper for that.
You have to thread that as a parameter through all your calls, trying to solve this with some kind of ambient storage, like TLS or AsyncLocal is probably not the best approach but it will probably work.
If you don't use async APIs you might get away with:
[ThreadLocal]
public static Guid InvocationId;
...but if you do use async, you can try:
public static AsyncLocal<Guid> InvocationId = new AsyncLocal<Guid>();
Good luck!
Related
This code comes directly from the Durable Function startup in Visual Studio 2019
[FunctionName("Orchestrator_HttpStart")]
public static async Task<HttpResponseMessage> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
[DurableClient] IDurableOrchestrationClient starter,
ILogger log)
{
// Function input comes from the request content.
string instanceId = await starter.StartNewAsync("Orchestrator", null);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return starter.CreateCheckStatusResponse(req, instanceId);
}
Where are the values for IDurableOrchestationClient starter & ILogger log coming from? Since these parameters wont be passed in the HTTP request, I'm assuming that there must be some IoC magic happening behind the scenes, but I'm not entirely sure what/where it is.
I'm assuming that there must be some IoC magic happening behind the scenes.
Correct.
Where is the value for IDurableOrchestrationClient coming from?
The IoC is from AddDurableTask (source). IDurableClientFactory creates IDurableClient which inherits from IDurableOrchestrationClient. You can find an example on usage of AddDurableTask here.
serviceCollection.TryAddSingleton<IDurableClientFactory, DurableClientFactory>();
Where is the value for ILogger coming from?
(as #Ian Kemp and #Nkosi already pointed out)
The IoC is from AddWebScriptHost (source). ILoggerFactory creates ILogger.
loggingBuilder.Services.AddSingleton<ILoggerFactory, ScriptLoggerFactory>();
I have an async Library for audio file processing. Furthermore I want to offer these Methods via Rest. So I made an MVC WebApi Project. The library needs some time to start, so I added a class that offers a way to init and exposes the libraries main object.
public static class MusicHandler
{
public static MusicCapture.MusicCapture MusicCapture;
public static void init()
{
MusicCapture = new MusicCapture.MusicCapture("D:\\Temp", "D:\\test", "E:\\FingerPrintDB2.ss");
MusicCapture.Start();
}
}
I start it in Application_Start()
protected void Application_Start()
{
MusicHandler.init();
}
Now when my init method contains some async calls like this:
var hashedFingerprints = command.Hash().Result;
The programm will just skip over these lines. They do not get executed for all I can tell.
Same thing happens when I call any of the objects async methods from my REST endpoints. When I run the library not from ASP.NET/MVC the code works flawlessly.
I found some comments that said that this is a problem because of deadlocks, but no advice or code how to avoid this/make this work.
Thank you in advance.
So, if I understand, you want to start something called a MusicHandler, which takes a little while to start up.
Once that has loaded, communication with your system will be via RESTful HTTP calls.
In your MusicHandler you can have a flag to state whether it has finished loading.
public static class MusicHandler
{
public static MusicCapture.MusicCapture MusicCapture;
public static bool Initialized {get;} = False;
public static void init()
{
MusicCapture = new MusicCapture.MusicCapture("D:\\Temp", "D:\\test", "E:\\FingerPrintDB2.ss");
MusicCapture.Start();
Initialized = true;
}
}
Then in your MVC Controller, you can examine this flag and return an error if initialization has not completed.
This way you don't need to worry about being async all the way to the top.
But I'm surprised you're using application_start at all... host this using kestrel and do this setup in program.cs or something, where you can be async to the top natively.
I figured my Problem out, it was twofold.
My library failing on start was a bug in the library that led to an exception which wasn't bubble up. I was able to mitigate this bug. Async calls on startup with a MVC App with .Result inside seem to actually be no problem.
My REST calls failing on async could be fixed by changing the rest controllers methods to async. I never would have thought thats possible but I found an example here: https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
// GET api/music
public async System.Threading.Tasks.Task<string> GetAsync()
{
string result = await MusicHandler.MusicCapture.DetectAsync(5);
Console.WriteLine("Server returning: " + result);
return result;
}
Is it ok to call activity functions from private methods in a Durable Function orchestrator, or should that be avoided? Here's an example:
[FunctionName(nameof(OrchFunc))]
public async Task OrchFunc(
[OrchestrationTrigger] DurableOrchestrationContext context,
ILogger logger) {
var myParameter = context.GetInput<string>();
// Any issue with doing this with the way checkpoints work?
var result = await MyPrivateFunc(context, myProperty);
}
private async Task<bool> MyPrivateFunc(
DurableOrchestrationContext context,
string myParameter) {
return result = await context.CallActivityAsync<bool>(nameof(MyActivityFunc), myParameter);
}
Keep in mind this is a simple example to clarify the question. I am already aware that it could be called directly from the orchestration function and thereby skip the private function. I'm not looking to see if it makes sense here, but rather just seeking to understand if there would be unintended side effects.
I imagine you've probably moved on from this issue, but for anyone else seeking this out, yes this should work fine. The context will be passed by reference so it will still be the one calling the activity function. Note, however, that the restrictions on orchestrations will still apply to the private method, so no awaiting anything called by something other than the context.
I have these methods in a WCF web service.
public async Task<bool> DoAsyncWork()
public List<Progress> GetProgress(string progressKey)
If it is possible I would like to get the progressKey from the DoAsyncWork method as soon the async work has started so I can show the progress to the user. The progress is saved in a database with the progressKey as a key for the work done by DoAsyncWork.
What I understand it is not a good practice to have an out parameter in a WCF service. So
public async Task<bool> DoAsyncWork(out string progressKey)
is not a solution.
The generic bool value is not returned until the Task has completed so I can't use the generic Task class to get the progressKey.
Pass in to your task method a callback that it can call to provide you with your progress. No need for an out parameter.
void myMethod(IProgressCallback callback)
{
... do some work
callback.NotifyProgress("Ive done some work");
}
I am writing a WCF webservice that includes a method that accepts an array of objects and inserts them into the database. This could take a long time, so I can't just expect the client to wait.
My colleague thinks that I don't need to do anything, that it's the client's job to call my service asynchronously. I just write a normal method. This doesn't sound right to me, although I hope it's true because looking at WCF async tutorials and SO questions has just confused me so far.
Is he correct? If not, how do I actually write the method in a way that would allow the client to call the method asynchronously or otherwise avoid hanging?
If he is correct (as appears to be the case), then what is the point of defining an asynchronous method ([OperationContract (AsyncPattern=true)], Begin, End, etc.). Is it a way explicitly handling asynchronous calls, or allowing interactivity, or what?
It should fall on the client's side. They are the ones that have to prevent their app/UI from hanging.
Have your client call your method asynchronously. If they are using a service reference, all methods/events are generated automatically.
myWcfClient.myMethodCompleted
+= new EventHandler<myMethodCompletedEventArgs>(myCallBack);
myWcfClient.myMethodAsync(args);
public void myCallback(object sender, myMethodCompletedEventArgs e)
{
var myResult = e.Result;
}
If your client doesn't care what happens with the service call, you want a simple fire and forget operation and you can do this.
The AsyncPattern property tells the runtime that your operations implement the .NET Framework asynchronous method design pattern. See here. If you want your client application to know what has happened with your service call then you can use this pattern. There are other ways to get the results though.
This is only on the client side, I've skipped the old event driven async bleh pattern and replaced it with the async-await pattern. Not waiting for webmethod calls async, and blocking the UI... doesn't even belong in this century ;)
If you are using .net 4.5+ you are getting the async-await pattern for free (Unless wp8, where you still have to wrap it). The async methods should already be avaliable through the service. I recommend the AsyncBridge if you are using old frameworks, which allows you to use the async-await pattern for cases like this. The alternative is to stick to the old event driven async nightmare. The examples below is only possible if you are using C#5.0 or never.
Ensure to start in a new thread from a non async method.
Task.Factory.StartNew(client.DoSomethingAsync("blabla") ).ContinueWith(...);
The last part is run after your method has completed, check for exceptions to completion code etc.
Or in some async method
public async Task<string> DoSomethingAsync(String text) {
// Exception handling etc
return await client.DoSomethingAsync(text);
}
wrapping APM to async-await pattern:
public class ServiceWrapper : IServiceWrapper
{
readonly YourServiceClient client;
public ServiceWrapper(YourServiceClient client)
{
this.client = client;
}
public async Task<string> DoSomethingAsync(string someParameter)
{
return await Task<string>.Factory.FromAsync(client.BeginDoSomeStuff, client.EndDoSomeStuff, someParameter, new object());
}
}
EDIT
Opening and closing connections in a wrapped service. (I don't have my devbox avaliable right now but this should work).
public class ServiceWrapper : IServiceWrapper
{
EndpointAddress address;
public ServiceWrapper(EndpointAddress clientAddress)
{
address = clientAddress;
}
public async Task<string> DoSomethingAsync(string someParameter)
{
// handle exceptions etc here, can be done some cleaner..
var client = new YourServiceClient();
client.Endpoint.Address = address.Address; // can skip this..
await client.OpenAsync()
var res = await Task<string>.Factory.FromAsync(client.BeginDoSomeStuff, client.EndDoSomeStuff, someParameter, new object());
await client.CloseAsync();
return res;
}
}
One last thing I'm not sure how you generate your proxy, if you are using vs make sure to hook of the checkbox allowing async methods when configuring the service. If you are using svcutil add the appropriate flags.
Async-await pattern
Old event driven async pattern
Hope it helps,
Cheers,
Stian