Reputation: 981
I have a 3rd party DLL with an asynchronous method that I want to wrap with another method that waits for its result.
I started writing a class to hide the functionality, but now I can't work out how to wait for Doc.Completed
to be called by the DLL after this.version.DownloadFile(this)
in Doc.Download
.
The DLL calls InitTransfer
, then OnProgressNotify
a number of times, then Completed
. OnError
may be called at any stage, but Completed
is always called last. I don't care about InitTransfer
, OnProgressNotify
or OnError
.
I have read Asynchronous call in synchronous method and Turn asynchronous calls into synchronous but I don't understand how to apply the answers to this case.
I'm using C# 4.
public class Doc : SomeInterfaceFromTheDll
{
private readonly IVersion version; // An interface from the DLL.
private bool downloadSuccessful;
public Doc(IVersion version)
{
this.version = version;
}
public bool Download()
{
this.version.DownloadFile(this);
return ??? // I want to return this.downloadSuccessful after Completed() runs.
}
public void Completed(short reason)
{
Trace.WriteLine(string.Format("Notify.Completed({0})", reason));
this.downloadSuccessful = reason == 0 ? true : false;
}
public void InitTransfer(int totalSize)
{
Trace.WriteLine(string.Format("Notify.InitTransfer({0})", totalSize));
}
public void OnError(string errorText)
{
Trace.WriteLine(string.Format("Notify.OnError({0})", errorText));
}
public void OnProgressNotify(int bytesRead)
{
Trace.WriteLine(string.Format("Notify.OnProgressNotify({0})", bytesRead));
}
}
Upvotes: 0
Views: 833
Reputation: 23721
This can be achieved using a ManualResetEvent as shown below. There are a few caveats though. The primary one being that this mechanism does not permit you to call Download()
on the same Doc
instance on multiple threads at the same time. If you need to do this, then a different approach may be required.
public class Doc : SomeInterfaceFromTheDll
{
private readonly IVersion version; // An interface from the DLL.
private readonly ManualResetEvent _complete = new ManualResetEvent(false);
private bool downloadSuccessful;
// ...
public bool Download()
{
this.version.DownloadFile(this);
// Wait for the event to be signalled...
_complete.WaitOne();
return this.downloadSuccessful;
}
public void Completed(short reason)
{
Trace.WriteLine(string.Format("Notify.Completed({0})", reason));
this.downloadSuccessful = reason == 0;
// Signal that the download is complete
_complete.Set();
}
// ...
}
Upvotes: 1