【问题标题】:Search photos and progressbar display搜索照片和进度条显示
【发布时间】:2019-01-30 03:33:11
【问题描述】:

我有一个带有搜索按钮和进度条的表单,用于在网络目录中查找照片。 它返回一个错误:

System.Reflection.TargetInvocationException
  HResult=0x80131604
  Message=O destino de uma invocação accionou uma excepção.
  Source=mscorlib
  StackTrace:
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Delegate.DynamicInvokeImpl(Object[] args)
   at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
   at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
   at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(Form mainForm)
   at _myprogram.Program.Main() in C:\Users\folder\Desktop\folder\folder\V10\folder\Program.cs:line 19
Inner Exception 1:
ArgumentOutOfRangeException: O índice estava fora do intervalo. Tem de ser não negativo e inferior ao tamanho da colecção.
Nome do parâmetro: índex

代码如下:

   public partial class FormProcuraFotos : Form
{
    public FormProcuraFotos()
    {
        InitializeComponent();
    }
    // We create the DataTable here so we can create the new inside the Worker_DoWork and use it also on the Worker_RunWorkerCompleted
    DataTable tableWithPhotos;
    private void button1_Click(object sender, EventArgs e)
    {
        // Make the progressBar1 to look like its allways loading something
        progressBar1.Style = ProgressBarStyle.Marquee;
        // Make it here visible
        progressBar1.Visible = true;
        var worker = new BackgroundWorker();

        // Event that runs on background
        worker.DoWork += this.Worker_DoWork;

        // Event that will run after the background event as finnished
        worker.RunWorkerCompleted += this.Worker_RunWorkerCompleted;
        worker.RunWorkerAsync();
    }

    // The reason for having this here was to work with the progress bar and to search for the photos and it will not block the UI Thread
    // My advice is to have them here and pass them to the next form with a constructor
    private void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        // We must create a list for all the files that the search it will find
        List<string> filesList = new List<string>();
        // Create the new DataTable to be used
        tableWithPhotos = new DataTable();
        tableWithPhotos.Columns.Add("Nome e formato do ficheiro (duplo clique para visualizar a imagem)");
        tableWithPhotos.Columns.Add("Caminho ( pode ser copiado Ctrl+C )");

        // What folders that we want to search for the files
        var diretorios = new List<string>() { @"‪C:\Users\folder\Pictures" };

        // What extensions that we want to search
        var extensoes = new List<string>() { ".jpg", ".bmp", ".png", ".tiff", ".gif" };

        // This 2 foreach are to search for the files with the extension that is on the extensoes and on all directories that are on diretorios
        // In for foreach we go through all the extensions that we want to search
        foreach (string entryExtensions in extensoes)
        {
            // Now we must go through all the directories to search for the extension that is on the entryExtensions
            foreach (string entryDirectory in diretorios)
            {
                // SearchOption.AllDirectories search the directory and sub directorys if necessary
                // SearchOption.TopDirectoryOnly search only the directory
                filesList.AddRange(Directory.GetFiles(entryDirectory, entryExtensions, SearchOption.AllDirectories));
            }
        }

        // And now here we will add all the files that it has found into the DataTable
        foreach (string entryFiles in filesList)
        {
            DataRow row = tableWithPhotos.NewRow();
            row[0] = Path.GetFileName(entryFiles);
            row[1] = entryFiles;
            tableWithPhotos.Rows.Add(row);
        }
    }
    private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // With the new constructor on the FormResultadosFotos, we pass the table like this so the form can receive it
        progressBar1.Visible = false;
        var NovoForm = new FormResultadosFotos(tableWithPhotos);
        NovoForm.Show();
    }
}

} 我有另一个表单可以在 datagridview 上显示这些结果(这个 datagridview 有一个图片框,如果用户双击则显示照片) 代码如下:

public partial class FormResultadosFotos : Form
{
    // This is the constructor that we have added to the FormResultadosFotos so it can receive the DataTable that was created on the previous form
    public FormResultadosFotos(DataTable table)
    {
        InitializeComponent();
        dataGridView1.DataSource = table;
        dataGridView1.Columns[1].Visible = true;
        // What can be done here to not block the UI thread if is being blocked while populating the dataGridView1, is to create another BackgroundWorker here and populate the dataGridView1 there
    }
}

}

是否可以帮助我并说明问题所在?谢谢。

【问题讨论】:

  • 你没有描述问题是什么,你只是给了我们两个(大)代码块并说“出了什么问题?”请更新您的问题,说明问题是什么以及您预计会发生什么。
  • 请不要包含任何与问题没有直接关系的代码。空方法就是其中之一。他们所做的只是占用空间。
  • 这来自他提出的另一个问题,stackoverflow.com/questions/51984123/…

标签: c# photo


【解决方案1】:

我会将 ProgressBar 更改为像 progressBar1.Style = ProgressBarStyle.Marquee; 那样继续,并且在 Worker_DoWork 上没有它,因为它在那里,但在某些方面什么也不做。 我建议的代码是这样的,BackgroundWorker 正在完成它的工作,搜索文件并且不阻塞 UI 线程 AKA 在执行可能需要很长时间的任务时不阻塞程序 在单击时,我们可以使其可见,然后在工作完成后使 Worker_RunWorkerCompleted 不可见。

我确实在此处更改了 Worker_DoWork,删除了 progressBar1 上的更新,因为它只是为了外观而没有做任何其他事情并让它完成它的工作,这个过程可能需要很长时间,这就是它们的用途

public partial class FormPesquisaFotos : Form
{
    // We create the DataTable here so we can create the new inside the Worker_DoWork and use it also on the Worker_RunWorkerCompleted
    DataTable tableWithPhotos;
    private void button1_Click(object sender, EventArgs e)
    {
        // Make the progressBar1 to look like its allways loading something
        progressBar1.Style = ProgressBarStyle.Marquee;
        // Make it here visible
        progressBar1.Visible = true;
        var worker = new BackgroundWorker();

        // Event that runs on background
        worker.DoWork += this.Worker_DoWork;

        // Event that will run after the background event as finnished
        worker.RunWorkerCompleted += this.Worker_RunWorkerCompleted;
        worker.RunWorkerAsync();
    }

    // The reason for having this here was to work with the progress bar and to search for the photos and it will not block the UI Thread
    // My advice is to have them here and pass them to the next form with a constructor
    private void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        // We must create a list for all the files that the search it will find
        List<string> filesList = new List<string>();
        // Create the new DataTable to be used
        tableWithPhotos = new DataTable();      
        tableWithPhotos.Columns.Add("Nome e formato do ficheiro (duplo clique para visualizar a imagem)");
        tableWithPhotos.Columns.Add("Caminho ( pode ser copiado Ctrl+C )");

        // What folders that we want to search for the files
        var diretorios = new List<string>() { @"\\Server\folder1\folder2" };

        // What extensions that we want to search
        var extensoes = new List<string>() {"*.jpg","*.bmp","*.png","*.tiff","*.gif"};

        // This 2 foreach are to search for the files with the extension that is on the extensoes and on all directories that are on diretorios
        // In for foreach we go through all the extensions that we want to search
        foreach (string entryExtensions in extensoes)
        {
            // Now we must go through all the directories to search for the extension that is on the entryExtensions
            foreach (string entryDirectory in diretorios)
            {
                // SearchOption.AllDirectories search the directory and sub directorys if necessary
                // SearchOption.TopDirectoryOnly search only the directory
                filesList.AddRange(Directory.GetFiles(entryDirectory, entryExtensions, SearchOption.AllDirectories));
            }
        }

        // And now here we will add all the files that it has found into the DataTable
        foreach (string entryFiles in filesList)
        {
            DataRow row = tableWithPhotos.NewRow();
            row[0] = Path.GetFileName(entryFiles);
            row[1] = entryFiles;
            tableWithPhotos.Rows.Add(row);
        }
    }
    private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // With the new constructor on the FormResultadosFotos, we pass the table like this so the form can receive it
        progressBar1.Visable = false;
        var NovoForm = new FormResultadosFotos(tableWithPhotos);
        NovoForm.Show();
    }
}

在 FormResultadosFotos 上,我们创建一个新的构造函数,它将接收 DataTable 并消除在此处搜索文件的需要,因为它们都已准备好放在桌子上

public partial class FormResultadosFotos : Form
{
    // This is the constructor that we have added to the FormResultadosFotos so it can receive the DataTable that was created on the previous form
    Public FormResultadosFotos(DataTable table)
    {
        InitializeComponent();
        dataGridView1.DataSource = table;
        dataGridView1.Columns[1].Visible = true;
        // What can be done here to not block the UI thread if is being blocked while populating the dataGridView1, is to create another BackgroundWorker here and populate the dataGridView1 there
    }

    private void dataGridView1_DoubleClick(object sender, EventArgs e)
    {
        var myForm = new FormPictureBox();
        string imageName = dataGridView1.CurrentRow.Cells[1].Value.ToString();
        var img = Image.FromFile(imageName);

        myForm.pictureBox1.Image = img;
        myForm.ShowDialog();
    }
}

要让 progressBar1 从 1 变为 100,您需要在搜索之前知道有多少文件等,因为我们不知道,让它从 1 变为100 不可​​能,至少据我所知,如果可能的话,请为此创建一个 anwser,因为我想知道如何

拥有它(您必须在 Class FormResultadosFotos 中具有其他方法,至少是基本构造函数)它将执行您想要的操作,在新线程 AKA BackgroundWorker 上搜索可能需要很长时间的文件如果在列表diretorios 上的目录中有任何"*.jpg","*.bmp","*.png","*.tiff","*.gif" 文件,它将把它们放在列表filesList 等等foreach 可以添加到DataTable

编辑:

即使我自己是葡萄牙语,也只是一点建议,在这里提问时,尽量不要用葡萄牙语写东西,使用英语,如 cmets 和变量,这样更容易阅读您的代码。

编辑 2:

使用我为您提供的代码,您可以从图片中看到:

这是程序download link的链接

正如您从我与您分享的信息中看到的那样,应该可以解决您确实遇到的问题,请查看我使用我为您提供的示例制作的程序的源代码

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 2016-04-10
    • 1970-01-01
    相关资源
    最近更新 更多