【问题标题】:C# Forms Loading ComboBox Items on StartupC# 窗体在启动时加载 ComboBox 项
【发布时间】:2015-06-07 13:21:11
【问题描述】:
public Form1()
{
    InitializeComponent();
    loadComboEmail();
}

private void loadComboEmail()
{
    string path = Directory.GetCurrentDirectory();
    string build = (path + "\\" + "email.txt");
    string[] lines = System.IO.File.ReadAllLines(build);

    comboEmail.Items.AddRange(lines);
    comboEmail.SelectedIndex=0;
}

我有一个组合框,我想加载存储在文本文件中的客户电子邮件地址。使用loadComboEmail(),我从文本文件中读取并加载Combobox。通过在表单启动时调用loadComboEmail,我是否在做一些被认为是不好的做法?如果是这样,我如何正确读取文本文件,然后将其加载到组合中,以便在加载表单时,它具有必要的数据?

【问题讨论】:

  • 没关系,虽然你会阻塞 UI 线程。
  • 最好执行此异步操作以避免 UI 冻结。
  • @MasihAkbari - 你能告诉我如何在 loadComboEmail() 方法中实现异步吗?

标签: c# combobox


【解决方案1】:

不,这似乎很合法。您不必担心,因为这是在WinForms 中加载所有内容的方式...这将在短时间内阻塞UI 线程,但是由于您不会加载大量内容,你甚至不会注意到它。

当您开始执行大量操作和大文件时,您应该考虑使用BackgroundWorkerTask

无论如何,您还应该考虑使用以下代码而不是您的代码:

private void loadComboEmail()
{
    string path = System.IO.Path.GetDirectoryName(Application.ExecutablePath); //seems to be the same to me, but is safer
    string build = System.IO.Path.Combine(path, "email.txt"); //much more safer then simple string addition
    string[] lines = System.IO.File.ReadAllLines(build);

    comboEmail.Items.AddRange(lines);
    comboEmail.SelectedIndex = 0;
}

【讨论】:

  • @Nexusfactor 没问题,我很高兴能为您提供帮助。如果我帮助了你,请将我的答案标记为已解决:D
  • 我只是想知道,线程是一个需要我花点时间才能理解的概念。看到我只是从文本文件中读取并加载一些表单控件,在我的情况下使用异步不是正确的吗?使用 Martijn van Put 给我的代码,它仍然说它会同步运行,所以使用他的正确没有关系?
  • @Nexusfactor 没错,因为您没有加载假设 200 MB 的文本并对其进行处理。所以您不必担心并立即使用它。
  • 谢谢,非常感谢。
【解决方案2】:

你可以使用:

 Task task = Task.Factory.StartNew(() =>
 {
    // Background work
    loadComboEmail();
 }).ContinueWith((t) => 
 {
    //If you need to execute something after the loading process.
 });

为了更新 UI 线程,您可以在另一个线程上进行阅读,当电子邮件列表加载时,只需更新它。

Task.Factory.StartNew(() =>
        {
            // Background work - read the file
        }).ContinueWith((t) => {
            // Update UI thread here

        }, TaskScheduler.FromCurrentSynchronizationContext());

【讨论】:

    【解决方案3】:

    使用构造函数加载不被认为是一种不好的做法。阅读 Hans Passant 关于何时应该使用窗口的加载事件的答案。 What setup code should go in Form Constructors versus Form Load event?

    尽管如 cmets 中所说,您正在阻塞 UI 线程。在构造函数中不能使用关键字 await。所以你必须“开火然后忘记”。使用Load 事件时,您可以使用await,但事件处理程序是async void。所以他们没有等待,你仍然有'Fire and forget'。

    public Form1()
    {
        InitializeComponent();
        loadComboEmail();
    }
    
    private async Task loadComboEmail()
    {
        string path = Directory.GetCurrentDirectory();
        string build = (path + "\\" + "email.txt");
        string[] lines = await Task.Run(() => File.ReadAllLines(build));
    
        comboEmail.Items.AddRange(lines);
        comboEmail.SelectedIndex=0;
    }
    

    【讨论】:

    • 它会运行,但会给出以下警告:警告 3 此异步方法缺少“等待”运算符,将同步运行。考虑使用 'await' 运算符来等待非阻塞 API 调用,或使用 'await Task.Run(...)' 在后台线程上执行 CPU 密集型工作。 C:\Users\Nexusfactor\documents\visual studio 2013\Projects\Crystal Message\Crystal Message\Form1.cs 30 28 Crystal Message
    • 正确,一些不正确的编码。请使用新样本重试。您现在仍然收到警告,因为无法在构造函数中完成等待。其他解决方案是使用 Olaru Mircea 所示的延续任务
    • @Martijn van Put - 我试过了。现在可以了。您是否有文章或在某个地方学到了所有这些(任务,等待)我想自己阅读和理解。
    • 现在很好用!是的,当然,看看这里:msdn.microsoft.com/en-us/library/hh191443.aspx。 o'Reilly 还有一本关于异步的好书:shop.oreilly.com/product/0636920026532.do
    • 快速提问,我注意到有时它会加载但组合框未加载,我必须关闭并重新打开应用程序。有什么原因吗?
    猜你喜欢
    • 1970-01-01
    • 2015-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-27
    • 1970-01-01
    相关资源
    最近更新 更多