Home > OS >  Creation of controls dynamically on a separate thread
Creation of controls dynamically on a separate thread

Time:09-25

I am developing a WPF app, to generate folders dynamically

Right now I have an issue with what happens if the user puts 10000 folders? I am trying to run my for loop in another thread

By the way, how can I limit the user to create x number of folders? Code Behind:

    public MainWindowVM() {

        SaveCommand = new Command(SaveAction);

        FoldersCollection = new ObservableCollection<FolderData>();

        CreateCommand = new Command(CreateAction);

        CreateFoldersCommand = new Command(CreateFolderAction);
    }

    private void SaveAction() {

    }

    private void CreateFolderAction() {

        var dirrName = "Assets";

        var workingDirectory = Environment.CurrentDirectory;

        // This will get the current PROJECT directory
        var projectDirectories = Directory.GetParent(workingDirectory).Parent.Parent.GetDirectories(dirrName)
            .ToList();

        var path = Path.GetFullPath(projectDirectories.First().FullName);

        foreach (var item in FoldersCollection) {
            Directory.CreateDirectory($"{path}\\{item.FolderName}");
        }
    }


    private void CreateAction() {
        for (int i = 0; i < Value; i  ) {

            Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate {
                FoldersCollection.Add(new FolderData() { FolderID = i, FolderName = string.Empty, Extenion = new List<string>() });

            }));

XAML:

<WrapPanel>
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="600" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="110" />
            <ColumnDefinition Width="400" />
        </Grid.ColumnDefinitions>

        <Label Content="Number of folders: " />

        <TextBox
            Grid.Column="1"
            VerticalAlignment="Center"
            PreviewTextInput="FolderNames_count"
            Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}" />

        <Button
            Grid.Column="1"
            HorizontalAlignment="Right"
            VerticalAlignment="Center"
            BorderBrush="Transparent"
            Command="{Binding CreateCommand}"
            Content="Create"
            Focusable="False" />

        <ScrollViewer
            Grid.Row="1"
            Grid.ColumnSpan="2"
            Margin="10"
            BorderBrush="Transparent"
            Focusable="False"
            HorizontalScrollBarVisibility="Auto">
            <ItemsControl ItemsSource="{Binding FoldersCollection}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock
                                Margin="0,10,0,0"
                                VerticalAlignment="Center"
                                FontStyle="Oblique"
                                Text="{Binding FolderID}" />
                            <syncfusion:SfTextBoxExt
                                Width="300"
                                Margin="10,10,0,0"
                                VerticalAlignment="Center"
                                Text="{Binding FolderName, UpdateSourceTrigger=PropertyChanged}"
                                Watermark="Folder Name" />
                        </StackPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ScrollViewer>


        <Button
            Grid.Row="2"
            VerticalAlignment="Center"
            Command="{Binding CreateFoldersCommand}"
            Content="Create structure"
            Style="{StaticResource MenuItem}" />

        <Button
            Grid.Row="2"
            Grid.Column="1"
            Margin="5,0,0,0"
            VerticalAlignment="Center"
            Command="{Binding SaveCommand}"
            Content="Save structure"
            Style="{StaticResource MenuItem}" />

   </Grid>
</WrapPanel>

The app works fine, but when I exit, I get this error

Error whe I close the app

btw I am doing this to allow numbers in my textbox

 private void FolderNames_count(object sender, TextCompositionEventArgs e) {

        if (!char.IsDigit(e.Text, e.Text.Length - 1))
            e.Handled = true;
    }

CodePudding user response:

If you commands run on separate thread, then it looks like the bg thread still running during GUI thread is finished.

My recommendation is to put the handling of this case to the Window.Closing handler, i.e. do notify thread to break the loop, e.g. set cancellation token.

The brutal option would be to call Enviroment.Exit(0) method in the Window.Closing or Window.Closed handler, to terminate all threads. See Environment.Exit(Int32) Method

CodePudding user response:

It's the loop should be executed on a background thread:

private void CreateAction()
{
    Task.Run(() =>
    {
        for (int i = 0; i < Value; i  )
        {
            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
                FoldersCollection.Add(new FolderData() { FolderID = i })));
        }
    });
}
  •  Tags:  
  • wpf
  • Related