Home > OS >  Create Instance of a Class on New Thread
Create Instance of a Class on New Thread

Time:07-21

I am creating an instance of a class that is in DLL and can't be modified. It loads images and it takes long time which freezes the WinForms UI.

Can I instantiate the class on a new thread?

var images = new AppImages(); // This to execute on new thread?
var cboData = new List<string>();
foreach(var image in images)
{
    cboData.Add(image); 
}
comboBox.DataSource = cboData;

I am trying to use

private void My()
{
    var images = ThreadPool.QueueUserWorkItem(GetAppImages);
     
    var cboData = new List<string>();
    foreach(var image in images)
    {
        cboData.Add(image); 
    }
    comboBox.DataSource = cboData;
}

private AppImages GetAppImages()
{
    return new AppImages();
}

but the threadPool doesn't return any value, it is just executing the code and I need the new instance to work with it later in the code.

Also, I can call the entire logic in a new thread because there are UI elements (the comboBox for example).

CodePudding user response:

I would suggest using Task.Run to initialize AppImages in a different thread, and await that task from the UI thread. So:

public async Task My()
{
    Task<AppImages> task = Task.Run(() => new AppImages());
    var images = await task;
    comboBox.DataSource = images.Images.ToList();
}

The use of await here means that the last line of the method still runs on the UI thread - but it won't block the UI while the task is running.

CodePudding user response:

You need to use Invoke. This can be used by non-UI threads to access UI elements (via the UI thread). This is done because only the UI thread can interact with UI elements.

Here's an example of the creation of a new thread, and waiting for 10 seconds just to pretend it is doing work, but after waiting (e.g. when the results/images are ready), and we want to modify UI elements we use Invoke.

private void button1_Click(object sender, EventArgs e) {
    Task.Run(() => {
        // load stuff that takes time: simulate by sleeping for 10 seconds
        Thread.Sleep(10000);
        
        var newText = "new button text";

        // now we want to change something in the UI, we use Invoke.
        this.Invoke(new Action(() => {
            this.button1.Text = newText;
        }));
    });
}

CodePudding user response:

You can wrap this code in a method and can call that method using

System.Threading.Tasks.Task.Run()

eg

void LoadData()
{ 

   var images = new AppImages(); // This to execute on new thread?
   var cboData = new List<string>();
   foreach(var image in images)
   {
      cboData.Add(image); 
   }
   comboBox.DataSource = cboData;
}

and call it like this

Task.Run(() => LoadData());

Please refer the doc from Microsoft Task.Run Method

  • Related