带有线程的多个用户控件写入各自的ListBoxes

时间:2014-04-17 07:08:03

标签: c# wpf multithreading user-controls

我在一个应用程序中使用4个WPF用户控件。 每个用户控件都会启动自己的线程来完成这些操作,最后我希望它们只更新各自用户控件中的ListBox。

我尝试在用户控件代码中使用静态变量来保存用户控件的实例或甚至是其ListBox,但这导致只写入最后一个用户控件列表框(由错误的线程)。

我甚至尝过这样的东西

private static ListBox1 = null;
private static ListBox2 = null;
private static ListBox3 = null;
private static ListBox4 = null;
private static ListBoxToUse;

然后初始化每个UserControl

if (ListBox1 == null)
{
    ListBox1 = this;
    ListToUse = this;
}
else if (ListBox2 == null)
{
    ListBox2 = this;
    ListToUse = this;
} ...

然后

ListBoxToUse.Dispatcher.BeginInvoke(new Action(delegate()
{
    ListBoxToUse.Items.Add("......");
}));

但这也不起作用。有什么建议吗?

编辑1: -

以下是我的线程代码

    private class CopyPortDevFileThread
    {
        public MyWorkingDirectoryInfo WorkingDirectory { get; set; }
        public PortableDeviceFile PortDevFileToCopy { get; set; }
        public string DestinationDir { get; set; }

        public void CopyFile()
        {
            Debug.WriteLine("CopyFile DestinationDir " + DestinationDir);
            // To fix Samsung NT-7000 bug of giving the Id when Path.GetFilename() is called
            string gfn = Path.GetFileName(PortDevFileToCopy.Id);
            string fn = DestinationDir + "\\" + gfn;
            WorkingDirectory.USBDevice.DownloadFile(PortDevFileToCopy, DestinationDir);
            if (!IsValidFilename(gfn))
            {
                // Rename file if name is okay
                if (IsValidFilename(PortDevFileToCopy.Name))
                {
                    int sec = 5;
                    while (sec > 0)
                    {
                        if (IsFileReady(fn))
                        {
                            File.Move(fn, Path.Combine(DestinationDir, PortDevFileToCopy.Name));
                            fn = Path.Combine(DestinationDir, PortDevFileToCopy.Name);
                            sec = 0;
                        }
                        else
                        {
                            Console.WriteLine("Waiting .....");
                            System.Threading.Thread.Sleep(1000);
                        }
                        sec -= 1;
                    }
                }
            }
        }
    }

然后从用户控件的代码中调用线程

    private void CopyPortDevDocument(PortableDeviceFile _file, string _destDir)
    {
        Debug.WriteLine("CopyPortDevDocument with destination directory " + _destDir);
        if (_file == null)
        {
            return;
        }
        if (_destDir == null)
        {
            return;
        }
        if ((System.IO.Directory.Exists(_destDir)))
        {
            CopyPortDevFileThread cpdft = new CopyPortDevFileThread();
            cpdft.WorkingDirectory = Pwd;
            cpdft.PortDevFileToCopy = _file;
            cpdft.DestinationDir = _destDir;
            Thread cpdfThread = new Thread(new ThreadStart(cpdft.CopyFile));
            cpdfThread.Start();

            LogOutput(@"creating " + _destDir + "\\" + _file.Name);
        }
    }

1 个答案:

答案 0 :(得分:1)

您不需要这些静态字段。只需在UserControl XAML中分配ListBox控件的x:Name属性即可。然后,您可以作为UserControl类的成员访问ListBox:

<UserControl x:Class="UserControlTest.MyUserControl" ...>
    <Grid>
        <ListBox x:Name="list" .../>
        ...
    </Grid>
</UserControl>

以上XAML在类list中创建ListBox类型的字段MyUserControl


更新:更改线程类的CopyFile方法,使其接受类型为object的参数,然后将该对象强制转换为UserControl引用:

public void CopyFile(object parameter)
{
    var userControl = parameter as MyUserControl;
    ...
}

然后使用UserControl引用参数启动您的线程,如下所示:

var cpdfThread = new Thread(new ParameterizedThreadStart(cpdft.CopyFile));
cpdfThread.Start(this); // where this is the UserControl reference

另一种方法是将UserControl引用作为属性添加到CopyPortDevFileThread类。

您可以使用CopyFile线程,而不是创建用于排除ThreadPool方法的新线程。致电ThreadPool.QueueUserWorkItem