mineroot
mineroot

Reputation: 1666

Calling method asynchronously in C#

I'm trying to create Video To Gif converter using WPF MediaKit (MediaDetector class) library to extract video frame by time. I wanna to run StartButton_OnClick method asynchronously using async/await.

I'm using the following code:

private async void StartButton_OnClick(object sender, RoutedEventArgs e)
{
    if (_openFile != null &&
        !String.IsNullOrEmpty(SaveToBox.Text))
    {
        await new LocalVideoConverter(_openFile.FileName, _from*1000, _to*1000,
            SaveToBox.Text, InterpolationMode.Low, new System.Drawing.Size(320, 240))
            .StartConverting();
    }
    else
        MessageBox.Show("Choose video file and enter path for Gif");
}

StartConverting() method:

public override Task StartConverting()
{
    return Task.Run(() =>
    {
        Encoder.Start(GifPath);
        Encoder.SetDelay(Ival);
        Encoder.SetRepeat(0);
        for (double i = From; i < To; i += Ival)
        {
            var frame = GetFrame(TimeSpan.FromMilliseconds(i));
            frame = ResizeImage(frame);
            AddFrame(frame);
        }
        Encoder.Finish();   
    });
}

GetFrame(TimeSpan ts) method:

protected override Image GetFrame(TimeSpan ts)
{
    var bitmapSource = _mediaDetector.GetImage(ts);
    using (var outStream = new MemoryStream())
    {
        BitmapEncoder enc = new BmpBitmapEncoder();
        enc.Frames.Add(BitmapFrame.Create(bitmapSource));
        enc.Save(outStream);
        return new Bitmap(outStream);
    }
}

Also MediaDetector class has public unsafe BitmapSource GetImage(TimeSpan position) method.


When I click on the StartButton, I get an System.InvalidOperationException with message "The calling thread cannot access this object because a different thread owns it" in this line of GetImage() method (look this)

if (string.IsNullOrEmpty(m_filename))

I the beginner in multi-threaded programming. How I can to solve this problem?

P.S. Sorry for my not good English:-)

Upvotes: 3

Views: 291

Answers (1)

user2380654
user2380654

Reputation:

You might be able to get around async/await by using BeginInvoke. Since it's WPF, I guess you could write

 private void StartButton_OnClick(object sender, RoutedEventArgs e) {
    if (_openFile != null && !String.IsNullOrEmpty(SaveToBox.Text)) {
        this.Dispatcher.BeginInvoke(new Action(delegate() {
            LocalVideoConverter lvc =  new LocalVideoConverter(_openFile.FileName, _from*1000, _to*1000,
            SaveToBox.Text, InterpolationMode.Low, new System.Drawing.Size(320, 240));
            lvc.StartConverting();
        }));
    } else
        MessageBox.Show("Choose video file and enter path for Gif");
}

BackgroundWorker might be possible as well, although I'd not recommend it.

Upvotes: 3

Related Questions