I'm using a NuGet package, FFMpegCore, to transcode videos in a Windows Service created with VS 2022. The package calls an Action during the transcoding process that gives status information which I'd like to return to the user using their org and person IDs. The problem is that I don't know how to access a non-static variable from the action. The variables are defined as non-static because multiple users can be transcoding video at the same time:
public string org_int = "";
public string person-int = "";
They are instantiated when the class is created:
CADEMedia media = new CADEMedia("151", "9655");
...
public class CADEMedia {
public CADEMedia(string _org_int, string person_int) {
org_int = _org_int;
person_int = _person_int;
}
...
The call to the FFMpegCore transcoding function looks like:
await FFMpegArguments
.FromFileInput(inputFile)
.OutputToFile(outputFile, true, options => options
.WithCustomArgument(customArguments)
.WithFastStart())
.NotifyOnProgress(progressHandler, videoDuration)
.ProcessAsynchronously();
Then the action, progressHandler, looks like this but neither org_int or person_int are accessible here and that's the problem. I need these values to know where to send the progress:
public Action<double> progressHandler = new Action<double>(p =>
{
signalR.SendSignalR(org_int, person_int, "message", p + "% Complete");
});
So, the primary question is: How can I access org_int and person_int from the Action? I can't change the Action because it's predefined in a 3rd party package that I didn't write.
The problem is in the definition of
progressHandler.Narrowing down to the basics:
Here,
progressHandleris a field, andnew Action<double>(...)is its field initializer. A field initializer is executed during instantiation of the containing class (CADEMedia). At that point in time,thisis not available yet. As you already noticed, it is impossible to accessorg_intandperson_intfrom within the initializer. That is because those properties simply do not exist yet. The compiler knows this, and will give an error:The solution is simple: replace
=with=>.This completely changes the code being generated.
progressHandleris now a property, andnew Action<double>(...)is the implementation of its getter. The getter is not executed until the property is actually used. At which point the containing class has already been properly instantiated and initialized.Specifically:
new Action<double>(...)being evaluated) whenever.NotifyOnProgress(progressHandler, videoDuration)is called.signalR.SendSignalR(org_int, person_int, "message", p + "% Complete")is executed whenever FFMpegCore calls the progress handler; a (repeated) consequence of.ProcessAsynchronously()being called.TL;DR
This should work fine: