0

My goal is to drag and drop a file out of my app into a dropzone of a website.

For that I've made this form:

public partial class Form2 : Form
{
    private DataObject File;

    public Form2(string filePath)
    {
        InitializeComponent();

        File = new DataObject();
        File.SetFileDropList(new StringCollection() { filePath });

        labelFileName.Text = Path.GetFileName(filePath);
    }

    private void labelFileName_MouseDown(object sender, MouseEventArgs e)
    {
        labelFileName.DoDragDrop(File, DragDropEffects.Copy);
    }
}

It works if I use it like this:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        
        var form2 = new Form2("C:\\testfile.txt");
        form2.ShowDialog();
    }
}

But drag and drop dosn't work if I use it in an async Task like this:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private async void buttonRunAsync_Click(object sender, EventArgs e)
    {
        await Task.Run(() => OpenForm2());
    }

    private async Task OpenForm2()
    {
        var form2 = new Form2("C:\\testfile.txt");
        form2.ShowDialog();

        // do some stuff based on dialog result
    }
}

I think that's because it's not running in the UI thread but I haven't found a good explanation and also I'm not sure if that's the problem.

Connell.O'Donnell
  • 3,603
  • 11
  • 27
  • 61
christian
  • 1
  • 1
  • 2
    Why do you think you need the async? – LarsTech Jan 05 '21 at 15:44
  • When you say "it doesn't work", can you describe in what way? It crashing with an exception? – WSC Jan 05 '21 at 16:32
  • The `Task.Run` method executes the provided delegate on a background thread. This is a problem in your case, because accessing UI elements in any other thread than the UI thread is not allowed. If your intention is to keep the main form responsive (unblocked) while showing the `form2` dialog, take a look at [this](https://stackoverflow.com/questions/33406939/async-showdialog) question. – Theodor Zoulias Jan 05 '21 at 18:01
  • @LarsTech I don't specifically need async for this. I need to show this dialog in an async task and then wait for the user to drag and drop and hit OK. – christian Jan 07 '21 at 07:10
  • @WSC The drag and drop functionality isn't working. I can't drag it out of my app. Everything else works fine. – christian Jan 07 '21 at 07:14
  • @TheodorZoulias I saw this question already, but it dosn't really apply to me. I need to wait for the user to hit OK on my form2, which is working like this. Just the drag and drop functionality is missing. – christian Jan 07 '21 at 08:05
  • There shouldn't be any reason for you to need to wrap this in async. I recommend you try it with synchronous code first (which will be much easier) and then evaluate if you need it to be async. As said above, `Task.Run` is going to complicate this a lot for you. – WSC Jan 07 '21 at 09:14
  • @WSC My app automates a process by using a Rest API. The whole process is running async. The API dosn't support large files yet but the website does. I want to use this as a workaround incase a file is too big. – christian Jan 07 '21 at 09:47
  • Christian I agree with WSC that you should leave all the UI interaction synchronous. My suggestion is to make asynchronous only the heavy non-UI related operations, that otherwise would block the UI and make it non-responsive. – Theodor Zoulias Jan 07 '21 at 14:51

1 Answers1

-1

Using Invoke like this fixed my problem:

private async Task OpenForm2()
{
    this.Invoke((MethodInvoker)delegate
    {
        var form2 = new Form2("C:\\testfile.txt");
        var result = form2.ShowDialog();
    });
}
christian
  • 1
  • 1