Can I create WinForms OpenFileDialog.ShowDialog without giving the main thread?

I have a WinForms program that then uploads a collection of files to its stream through a stream stream used to report overall progress and shutdown. Each file will be loaded in its own stream, and then after downloading it will be transferred to its own conversion thread through the second batch stream through the main stream. The reason for this redirection through the main stream is that the main stream may offer the user to save space for the converted version of all these files after downloading the first file.

The problem I ran into is that the OpenFileDialog.ShowDialog () method (which is used to get the save directory from the user) blocks the main thread callback from the first completed load thread. This, in turn, allows other download threads to complete (not a problem), but then also start executing their callbacks in the main thread, after which they all fall into OpenFileDialog.ShowDialog (), which they would not otherwise have done, since my second a batch stream works with the first conversion, and as a result, they can be added to the batch stream manager.

I am using Dispatcher.CurrentDispatcher.BeginInvoke (myCallbackDelegate, DispatcherPriority.Normal, myParameter) to make a callback to the main topic when the item completes. To demonstrate the problematic code, I created a simplified example below.

public partial class TestForm : Form
{
    private readonly Dispatcher dispatcher = Dispatcher.CurrentDispatcher;

    //An instance of my own BatchBackgroundWorkerThread<T> class; this class parrarlelizes tasks and can report their individual and overall progress, completion and cancellation.
    private readonly BatchBackgroundWorkerThread<int> conversionBatchBackgroundWorker = new BatchBackgroundWorkerThread<int>();

    public TestForm()
    {
        InitializeComponent();

        for (int threadIndex = 0; threadIndex < 4; threadIndex++)
        {
            new Thread(DoSomeBackgroundWork).Start(threadIndex);
            Thread.Sleep(10);
        }
    }

    private void DoSomeBackgroundWork(object threadIndex)
    {
        Thread.Sleep(1000);

        dispatcher.BeginInvoke(new ParameterizedThreadStart(WorkCompletedCallback), DispatcherPriority.Normal, threadIndex);
    }

    private void WorkCompletedCallback(object threadIndex)
    {
        //Waits for CanQueueNewItems to be in a valid readable state.
        conversionBatchBackgroundWorker.WaitForPendingRun();

        //CanQueueNewItems is true when the batch background worker batch thread has been launched and its internal CountdownEvent and cancellationState have been initialized.
        if (conversionBatchBackgroundWorker.IsBusy && conversionBatchBackgroundWorker.CanQueueNewItems)
            //Queues the item in the BatchBackgroundWorker for parrarelization with any other items.
            //NOTE: This code is not currently hit unless the user makes a dialog selection before another callback can reach the above if statement.
            conversionBatchBackgroundWorker.Additem(threadIndex);
        else
        {
            FolderBrowserDialog.ShowDialog();

            conversionBatchBackgroundWorker.RunWorkerAsync(new int[] { (int)threadIndex }, FolderBrowserDialog.SelectedPath);
        }
    }
}

I tried changing the DispatcherPriority to DispatcherPriority.SystemIdle - this caused all ShowDialog dialogs to appear before clicking OK or Cancel on each of them, but otherwise the result was the same.

Is there a way to stop ShowDialog to allow other pending callbacks to be executed in the main thread?

Update: , , . BatchBackgroundWorker, . ShowDialog(), , , BatchBackgroundWorker, ( BatchBackgroundWorker ).

+4
1

, .

wasDialogShown = true;
OpenFileDialog.ShowDialog();

, wasDialogShown:

private readonly object dialogLock = new Object();

private void WorkCompletedCallback(object threadIndex)
{
    bool wasShown;
    lock(dialogLock) {
        wasShown = wasDialogShown;
        wasDialogShown = true;
    }
    if (wasShown) {
        MessageBox.Show("Success!");
    } else {
        OpenFileDialog.ShowDialog();
    }
}

, wasDialogShown , , , true.


( )

, 2 : dialogLaunched conversionWorkerLaunched. . , , , , , . , , . , , .

+1

Source: https://habr.com/ru/post/1611186/


All Articles