不确定如何在线程之间传递对象
Unsure of how to pass object between threads
我意识到我之前问过一个非常相似的问题,但是我的结构是错误的。我错误地认为我可以在 Invoke 中执行我的图标生成。这导致了另一个问题。
我有一个包含 500 个 SVG 的文件夹。我想在文件夹中创建每个 SVG 的对象。我需要在一个单独的线程上执行此操作,因为它可能需要一些时间才能完成,并且正在锁定 UI.
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
Thread t = new Thread(LoadIcons);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
private void LoadIcons()
{
//Populate ListOfSVGsInFolder
Foreach(String SVGFile in ListOfSVGsInFolder)
{
Icon icon = new Icon
//Perform ~50 lines of code which get the paths and other details from the
//SVGFile and plug them into my icon object
//Now I had a fully generated Icon
//Add the icon to the form
WrapPanel.Children.Add(icon)
}
}
我的问题是我无法将图标添加到 WrapPanel。因为我希望这段代码在单独的线程上执行,所以我不能直接与 UI 对话。但是,我可以这样做:
Foreach(String SVGFile in ListOfSVGsInFolder)
{
Icon icon = new Icon
//Perform ~50 lines of code which get the paths and other details from the
//SVGFile and plug them into my icon object
Dispatcher.Invoke(new Action(() =>
{
WrapPanel.Children.Add(icon);
}));
}
但在这样做时,我现在无法在尝试将其添加到 WrapPanel 时访问我的图标对象。
基本上,我希望能够对文件夹中找到的 SVG 执行所有这些计算,在同一线程中创建 SVG 的对象,然后将这些对象添加到 UI。
您需要一个图标列表:
List<Icon> iconList = new List<Icon>();
在加载图标中:
// ... build your icon here
lock(iconList)
{
iconList.Add(icon);
}
在您的 UI 主题中:
lock(iconList)
{
icon = iconList[0];
}
// use the icon in the GUI
当然,如果列表中有内容,您必须检查 UI 线程,并从此列表中删除 'used' 个图标,所有图标都在 lock()[=13= 中]
Thread t = new Thread(LoadIcons); //Don't do this
一般不要创建线程来做后台工作。正确管理它们对系统和您自己来说都是很多工作。而是使用线程池。
最简单的方法是使用 TaskFactory
:
foreach(string svgFile in listOfSVGsInFolder)
{
Task.Run(() => // Task.Factory.StartNew for pre .net 4.5
{
Debug.WriteLine ("Creating SVG in thread {0}", Thread.CurrentThread.ManagedThreadId);
Icon icon = // whatever you do to create it
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
() => {
WrapPanel.Children.Add(icon);
});
});
}
这就是为什么有 BackgroundWorker
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
BackgroundWorker bgWorker = new BackgroundWorker();
bgWorker.DoWork += LoadIcons;
bgWorker.ProgressChanged += IconDone;
bgWorker.RunWorkerAsync();
}
private void IconDone(object sender, ProgressChangedEventArgs e)
{
Icon icon = e.UserState as Icon;
if (icon != null)
WrapPanel.Children.Add(icon); //This code is executed in the GUI thread
}
private void LoadIcons(object sender, DoWorkEventArgs doWorkEventArgs)
{
BackgroundWorker worker = sender as BackgroundWorker;
//Populate ListOfSVGsInFolder
foreach (String SVGFile in ListOfSVGsInFolder)
{
Icon icon = new Icon
//Perform ~50 lines of code which get the paths and other details from the
//SVGFile and plug them into my icon object
//Now I had a fully generated Icon
worker.ReportProgress(0, icon);
}
}
更多信息:MSDN
我意识到我之前问过一个非常相似的问题,但是我的结构是错误的。我错误地认为我可以在 Invoke 中执行我的图标生成。这导致了另一个问题。
我有一个包含 500 个 SVG 的文件夹。我想在文件夹中创建每个 SVG 的对象。我需要在一个单独的线程上执行此操作,因为它可能需要一些时间才能完成,并且正在锁定 UI.
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
Thread t = new Thread(LoadIcons);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
private void LoadIcons()
{
//Populate ListOfSVGsInFolder
Foreach(String SVGFile in ListOfSVGsInFolder)
{
Icon icon = new Icon
//Perform ~50 lines of code which get the paths and other details from the
//SVGFile and plug them into my icon object
//Now I had a fully generated Icon
//Add the icon to the form
WrapPanel.Children.Add(icon)
}
}
我的问题是我无法将图标添加到 WrapPanel。因为我希望这段代码在单独的线程上执行,所以我不能直接与 UI 对话。但是,我可以这样做:
Foreach(String SVGFile in ListOfSVGsInFolder)
{
Icon icon = new Icon
//Perform ~50 lines of code which get the paths and other details from the
//SVGFile and plug them into my icon object
Dispatcher.Invoke(new Action(() =>
{
WrapPanel.Children.Add(icon);
}));
}
但在这样做时,我现在无法在尝试将其添加到 WrapPanel 时访问我的图标对象。
基本上,我希望能够对文件夹中找到的 SVG 执行所有这些计算,在同一线程中创建 SVG 的对象,然后将这些对象添加到 UI。
您需要一个图标列表:
List<Icon> iconList = new List<Icon>();
在加载图标中:
// ... build your icon here
lock(iconList)
{
iconList.Add(icon);
}
在您的 UI 主题中:
lock(iconList)
{
icon = iconList[0];
}
// use the icon in the GUI
当然,如果列表中有内容,您必须检查 UI 线程,并从此列表中删除 'used' 个图标,所有图标都在 lock()[=13= 中]
Thread t = new Thread(LoadIcons); //Don't do this
一般不要创建线程来做后台工作。正确管理它们对系统和您自己来说都是很多工作。而是使用线程池。
最简单的方法是使用 TaskFactory
:
foreach(string svgFile in listOfSVGsInFolder)
{
Task.Run(() => // Task.Factory.StartNew for pre .net 4.5
{
Debug.WriteLine ("Creating SVG in thread {0}", Thread.CurrentThread.ManagedThreadId);
Icon icon = // whatever you do to create it
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
() => {
WrapPanel.Children.Add(icon);
});
});
}
这就是为什么有 BackgroundWorker
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
BackgroundWorker bgWorker = new BackgroundWorker();
bgWorker.DoWork += LoadIcons;
bgWorker.ProgressChanged += IconDone;
bgWorker.RunWorkerAsync();
}
private void IconDone(object sender, ProgressChangedEventArgs e)
{
Icon icon = e.UserState as Icon;
if (icon != null)
WrapPanel.Children.Add(icon); //This code is executed in the GUI thread
}
private void LoadIcons(object sender, DoWorkEventArgs doWorkEventArgs)
{
BackgroundWorker worker = sender as BackgroundWorker;
//Populate ListOfSVGsInFolder
foreach (String SVGFile in ListOfSVGsInFolder)
{
Icon icon = new Icon
//Perform ~50 lines of code which get the paths and other details from the
//SVGFile and plug them into my icon object
//Now I had a fully generated Icon
worker.ReportProgress(0, icon);
}
}
更多信息:MSDN