0

How can I wait a method to finish or converting to Sync ?

My idea is that when I call CaptureImage() the program will wait until the image is captured at bmp = new Bitmap(screenshot.ToBitmap()); in void Callback(IAsyncResult result)

The problem is that sometimes it's trying to process the image before it's captured and I'm getting a black screen as result

This is my code:

DateTime start;

private void CaptureImage()
{
    start = DateTime.Now;
    progressBar1.Maximum = 1;
    progressBar1.Step = 1;
    progressBar1.Value = 0;

    DoRequest();
}

void DoRequest()
{
    try
    {
        progressBar1.Invoke(new MethodInvoker(delegate ()
        {
            if (progressBar1.Value < progressBar1.Maximum)
            {
                progressBar1.PerformStep();

                Size? resize = null;
                _captureProcess.CaptureInterface.BeginGetScreenshot(new Rectangle(0, 0, 0, 0), new TimeSpan(0, 0, 2), Callback, resize, (ImageFormat)Enum.Parse(typeof(ImageFormat), "Bitmap"));
            }                    
        }));
    }
    catch
    {

    }
}

public IAsyncResult BeginGetScreenshot(Rectangle region, TimeSpan timeout, AsyncCallback callback = null, Size? resize = null, ImageFormat format = ImageFormat.Bitmap)
{
    Func<Rectangle, TimeSpan, Size?, ImageFormat, Screenshot> getScreenshot = GetScreenshot;

    return getScreenshot.BeginInvoke(region, timeout, resize, format, callback, getScreenshot);
}

void Callback(IAsyncResult result)
    {
        Screenshot screenshot;
        try
        {
            screenshot = _captureProcess.CaptureInterface.EndGetScreenshot(result);
        }
        catch
        {
            screenshot = null;
        }

        if (screenshot != null)
        {
            using (screenshot)
                try
                {
                    _captureProcess.CaptureInterface.DisplayInGameText("Screenshot captured...");
                    if (screenshot != null && screenshot.Data != null)
                    {
                        bmp = new Bitmap(screenshot.ToBitmap());
                    }

                    Thread t = new Thread(new ThreadStart(DoRequest));
                    t.Start();
                }
                catch
                {
                }
            while (!result.IsCompleted)
            {
                Thread.Sleep(200);
            }
        }
    }

public Screenshot GetScreenshot(Rectangle region, TimeSpan timeout, Size? resize, ImageFormat format)
{
    lock (_lock)
    {
        Screenshot result = null;
        _requestId = Guid.NewGuid();
        _wait.Reset();

        SafeInvokeScreenshotRequested(new ScreenshotRequest(_requestId.Value, region)
        {
            Format = format,
            Resize = resize,
        });

        _completeScreenshot = (sc) =>
        {
            try
            {
                Interlocked.Exchange(ref result, sc);
            }
            catch
            {
            }
            _wait.Set();

        };

        _wait.WaitOne(timeout);
        _completeScreenshot = null;
        return result;
    }
}

Please let me know if there's something missing or I can improve my question

Thank you

EDIT:

I've tested by changing the method public IAsyncResult BeginGetScreenshot

Instead of this:

Func<Rectangle, TimeSpan, Size?, ImageFormat, Screenshot> getScreenshot = GetScreenshot;

return getScreenshot.BeginInvoke(region, timeout, resize, format, callback, getScreenshot);

Testing with this:

Func<Rectangle, TimeSpan, Size?, ImageFormat, Screenshot> getScreenshot = GetScreenshot;

IAsyncResult result = getScreenshot.BeginInvoke(region, timeout, resize, format, callback, getScreenshot);

while (!result.IsCompleted)
{
    Thread.Sleep(100);
}

getScreenshot.EndInvoke(result);

return result;

But I got System.InvalidOperationException: 'You can only call EndInvoke once for each asynchronous operation.'

kuhi
  • 531
  • 5
  • 23
  • If you call BeginInvoke to start it, you have to call EndInvoke to wait for it to finish. See also [Is EndInvoke really necessary?](https://stackoverflow.com/a/4585209/2791540) – John Wu Mar 31 '20 at 19:57
  • Edited the question testing with EndInvoke, but I think there's something I'm doing wrong – kuhi Mar 31 '20 at 20:23
  • I'm not sure why you'd want to make it async - I've never had a screenshot take more than a couple of milliseconds to retrieve; who can't wait that long? – Caius Jard Mar 31 '20 at 20:23
  • Because if I call it and there's any code after the call it will just skip it, for example doing CaptureImage() ; Thread.Sleep(1000); it will only do the Sleep and will skip the call to CaptureImage(); and it's async because this is code from https://github.com/spazzarama/Direct3DHook and I'm trying to make it sync instead of async because as you said I don't understand why can't wait to process it only few miliseconds – kuhi Mar 31 '20 at 20:30

0 Answers0