.NET Core 3.0 is the latest version of .NET Core and now supports WinForms and WPF. This sample shows how you can perform fill data to Autocomplete TextBox in another thread without slow down the main UI (User Interface). With this sample, you can do a better user experience for the end-user.

TextBox Autocomplete
Autocomplete helps the user to search/type from a know list. In my application, I build a list to Autocomplete with > 10.000 items and is very fast even on slow computers.

Autocomplete is an old feature, but this POST will demonstrate how to perform his use to load data fastly already in NET Core 3.0.

When you fill a Collection, if you have a huge suggestion list, this will make the UI (User Interface) freezes. But if you process in another thread the UI will not have any issues.

More technical information you can have here.

How it works

Like the other POST what uses a delegate, here, we use another thread to load data and delegate to bind the Autocomplete Collection in the current UI thread.
using System;  
using System.Data.SqlClient;  
using System.Drawing;  
using System.Windows.Forms;  
 
namespace TextBoxWithAutoComplete  
{  
 
    /// <summary>  
    /// 10-10-2019  
    /// </summary>  
    public partial class Form1 : Form  
    {  
 
        private TextBox textBox1;  
        public Form1()  
        {  
            InitializeComponent();  
 
            textBox1 = new TextBox  
            {  
                Location = new Point(0, 0),  
                Size = new Size(100, 32),  
                Visible = true,  
                TabIndex = 0  
            };  
            Controls.Add(textBox1);  
 
            Load += Form1_Load;  
        }  
 
        public void Form1_Load(object sender, EventArgs e)  
        {  
            Show(); // You need to show the form to avoid a thread error  
 
            LoadData(); // Start to load Data  
        }  
 
        private SqlConnection GetConnection()  
        {  
            // Init your connection  
            var oCnn = new SqlConnection  
            {  
                ConnectionString = "YOUR_CONNECTION_STRING"  
            };  
            oCnn.Open();  
            return oCnn;  
        }  
 
 
        #region TreadSafeLoading  
        private delegate void UpdateUIDelegate(AutoCompleteStringCollection myCollection);  
 
        /// <summary>  
        /// Load Data - You can make public to load as you need  
        /// </summary>  
        private void LoadData()  
        => // Start this process in a new thread  
            new System.Threading.Thread(() => OutOfThreadProcess()).Start();  
        // You can start others, every one in a new thread!  
 
        /// <summary>  
        /// Start fill in another Thread  
        /// </summary>  
        private void OutOfThreadProcess()  
        {  
            // inialize the collection  
            var myCollection = new AutoCompleteStringCollection();  
            using var oCnn = GetConnection();  
 
            // Start your SQL Query  
            var cmd = new SqlCommand($"Select [FirstName] + ' ' + [LastName] as [contactName] From [AdventureWorks].[Person].[Contact] Order By [FirstName], [LastName]", oCnn);  
 
            // Read and fill the collection  
            using var reader = cmd.ExecuteReader();  
            while (reader.Read())  
                myCollection.Add(reader.GetString(0));  
 
            // Invoke in a UI thread  
            _ = Invoke(new UpdateUIDelegate(UpdateUIInvoke), myCollection);  
        }  
 
        /// <summary>  
        /// Current UI Thread threatment  
        /// </summary>  
        /// <param name="myCollection"></param>  
        private void UpdateUIInvoke(AutoCompleteStringCollection myCollection)  
        {  
            // Setup up in corrent UI Thread  
            textBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;  
            textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;  
            textBox1.AutoCompleteCustomSource = myCollection;  
#if (IS_TELERIK_RadTextBoxControl)  
            // If you use Telerik  
            // I found an issue in Telerik by Progress, without fix.  
            if (ParentForm != null)  
                ParentForm.FormClosing += new FormClosingEventHandler(UIFormClosing);  
#endif  
        }  
#if (IS_TELERIK_RadTextBoxControl)  
        private void UIFormClosing(object sender, FormClosingEventArgs e) => textBox1.AutoCompleteCustomSource = null;  
 
#endif  
        #endregion  
 
    }  
}  

Observation

When you use this technic may you receive errors if you run the new thread without fire the Show() method from the form, this occurs because the current window(form) hasn't the Handle initialized.

Conclusion
I design this technic when I upgrade to .NET Core 3 and develop a fix for the FileSystemWatcher event that fires in a new thread, so I took the same idea to make Autocomplete load collection works in a new thread.