Reputation: 443
I've a scenario:
cameraCapture
callbackFunction
callbackFunction
(I have a photo captured) completes, I do more stuff. So I have to wait for callbackFunction
to complete before executing another function. How could i do this?
Here my code:
private static readonly Plustek_Camera.PFNCK_EVENT staticFnCamera = fnPFNCK_EVENT;
public static bool fnPFNCK_EVENT(int iEvent, int iParam, IntPtr pUserData)
{
//capture picture and save to folder
}
//I implement callback start camera and fire a callback staticFnCamera
var _status = CameraCtrl.Start(CameraCtrl.ScanMode, CameraCtrl.Resolution, CameraCtrl.ImageFormat, CameraCtrl.Alignment, staticFnCamera);
//waiting for staticFnCamera complete make sure image produced
ReadPassPortText();
Upvotes: 0
Views: 945
Reputation: 443
After try some implement callback waiting, i try to resolve by adding another form for capturing images (frmSecond).
frmFirst call frmSecond and waiting in 5 to 7 seconds to make sure capture completed.
after that processing ReadPassPortText()
frmFirst Code:
frmReadPassport frmReadPass = new frmReadPassport();
frmReadPass.ShowDialog();
ReadPassPortText();
frmSecondCode
private CAMERACTRL CameraCtrl = null;
//Add static for call from camera start , make sure this alive
private static Plustek_Camera.PFNCK_EVENT staticFnCamera ;
public frmReadPassport()
{
InitializeComponent();
staticFnCamera = fnPFNCK_EVENT;
}
Timer formClose = new Timer();
private void frmReadPassport_Load(object sender, EventArgs e)
{
CaptureImages();
formClose.Interval = 7000; // 7 sec
formClose.Tick += new EventHandler(formClose_Tick);
formClose.Start();
}
private void formClose_Tick(object sender, EventArgs e)
{
//free camera first
// check if camera start then stop
ReleaseResourceCamera();
staticFnCamera =null;
formClose.Stop();
formClose.Tick -= new EventHandler(formClose_Tick);
this.Dispose();
this.Close();
}
private void CaptureImages()
{
CameraCtrl = new CAMERACTRL();
CameraCtrl.LoadCameraDll();
CameraCtrl.GetDeviceList();
String temp = CameraCtrl.GetParameter();
CameraCtrl.Start(CameraCtrl.ScanMode,CameraCtrl.Resolution,CameraCtrl.ImageFormat, CameraCtrl.Alignment, staticFnCamera);
}
public static bool fnPFNCK_EVENT(int iEvent, int iParam, IntPtr UserData)
{
captureImage();
return true;
}
}
Upvotes: 0
Reputation: 70671
If I understand correctly, you have some camera control that provides an asynchronous API to start capturing an image, but you want to wait synchronously for that operation to complete.
If so, there are lots of different ways to accomplish what you're trying to do. One such way would be to use a TaskCompletionSource
:
TaskCompletionSource<bool> source = new TaskCompletionSource<bool>();
var _status = CameraCtrl.Start(CameraCtrl.ScanMode, CameraCtrl.Resolution,
CameraCtrl.ImageFormat, CameraCtrl.Alignment,
(iEvent, iParam, pUserData) =>
{
staticFnCamera(iEvent, iParam, pUserData);
source.SetResult(true);
});
//waiting for staticFnCamera complete make sure image produced
await source.Task;
ReadPassPortText();
Note that the above uses await
, which is valid only in an async
method. You haven't provided enough context to show exactly how that would work in your code, but I strongly recommend following the above. That will avoid blocking the currently running thread; the async
method will return at that point, letting the thread continue to run, and will be resumed at the ReadPassPortText();
statement when the operation completes.
If for some reason you simply cannot use the await
in your method, you can instead simply do source.Task.Wait();
. This will, of course, block the currently executing thread at that statement.
The above requires .NET 4.5. There are other approaches that work with earlier versions of .NET, but you would need to be specific about your requirements to make it worth trying to describe those.
Edit:
Since you are using .NET 4.0, and presumably Visual Studio 2010, the above won't work for you "out-of-the-box". One option is to download the Async CTP for Visual Studio, which will give you the C# 5.0 compiler that would enable the above. But if that's not feasible for you, another option is to just do what the compiler would do on your behalf, by replacing the last two lines above with the following:
source.Task.ContinueWith(task => ReadPassPortText(),
TaskScheduler.FromCurrentSynchronizationContext());
That would attach the continuation delegate that call ReadPassPortText()
to the Task
object from the TaskCompletionSource
, specifying the current synchronization context as the source of the scheduler to use to actually run the continuation.
The method would return after calling ContinueWith()
(just as it would in the await
version, except that here it's written out explicitly instead of the compiler doing it for you). When the Task
object is set to the completed state, the previously-registered continuation will be executed.
Note that your original question isn't very clear about the context. If the code is running in the UI thread, then using FromCurrentSynchronizationContext()
is important and will ensure that the continuation is executed in the UI thread as well. Otherwise, you can probably get away without specifying a scheduler in the call to ContinueWith()
.
Upvotes: 1
Reputation: 141512
This demonstrates an async-await pattern that you can use. As Peter Duniho points out in the comments, you will have to adapt the pattern to the API that you're using. Try playing with it here at this fiddle to understand how these things work.
using System;
using System.Threading.Tasks;
public class MyApp
{
public static void Main()
{
Console.WriteLine("1. MyApp calls camera capture.");
CameraCaptureAsync().Wait();
}
public async static Task CameraCaptureAsync()
{
Console.WriteLine("2. That calls callbackFunction");
var task = CallbackFunction();
Console.WriteLine("4. In the meantime.");
Console.WriteLine("5. Do some other stuff. ");
await task;
Console.WriteLine("7. Process the " + task.Result);
DoMoreStuff();
}
public async static Task<string> CallbackFunction()
{
Console.WriteLine("3. Which takes a picture.");
await Task.Delay(100);
Console.WriteLine("6. After the callback functions completes");
return "Photograph";
}
public static void DoMoreStuff()
{
Console.WriteLine("8. Do more stuff.");
}
}
Upvotes: 0