C# 使用后台工作程序时丢失UI功能
我对使用不同的线程和C# 使用后台工作程序时丢失UI功能,c#,wpf,multithreading,wcf,backgroundworker,C#,Wpf,Multithreading,Wcf,Backgroundworker,我对使用不同的线程和BackgroundWorker非常陌生,因此我还没有完全理解所有内容。我已经在下面的程序客户端发布了所有代码 我遇到的问题是,即使我使用了BackgroundWorker,当我将数据从WCF服务加载到WPF客户端应用程序时,仍然会丢失所有UI的功能。加载数据(大约+-1500行数据)大约需要2-3分钟,因此会造成非常糟糕的用户体验 当数据加载到datagrid中时,我是否缺少任何明显的东西来让UI工作?任何建议都将不胜感激,谢谢!:) 更新代码: public partia
BackgroundWorker
非常陌生,因此我还没有完全理解所有内容。我已经在下面的程序客户端发布了所有代码
我遇到的问题是,即使我使用了BackgroundWorker
,当我将数据从WCF服务加载到WPF客户端应用程序时,仍然会丢失所有UI的功能。加载数据(大约+-1500行数据)大约需要2-3分钟,因此会造成非常糟糕的用户体验
当数据加载到datagrid
中时,我是否缺少任何明显的东西来让UI工作?任何建议都将不胜感激,谢谢!:)
更新代码:
public partial class pgSysproStock : Window
{
public pgSysproStock()
{
InitializeComponent();
SysproStock.WindowState = WindowState.Normal;
dgSysproStock.IsEnabled = false;
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.WorkerReportsProgress = true;
worker.ProgressChanged += worker_ProgressChanged;
worker.RunWorkerAsync();
}
private readonly BackgroundWorker worker = new BackgroundWorker();
private async void worker_DoWork(object sender, DoWorkEventArgs e)
{
using (TruckServiceClient TSC = new TruckServiceClient())
{
List<AllStock> allStock = new List<AllStock>();
this.Dispatcher.Invoke((Action)(() =>
{
prgStockProgress.Visibility = Visibility.Visible;
}));
foreach (var item in await TSC.GetSysproStockAsync())
allStock.Add(new AllStock
{
Id = item.Id,
StockCode = item.StockCode,
Description = item.Description,
ConvFactAltUom = item.ConvFactAltUom,
ConvMulDiv = item.ConvMulDiv,
ConvFactOthUom = item.ConvFactOthUom,
MulDiv = item.MulDiv,
Mass = item.Mass,
Updated_Supplier = item.Updated_Supplier,
CycleCount = item.CycleCount,
ProductClass = item.ProductClass.ToString(),
UnitCost = item.UnitCost,
Discount = item.Discount,
Warehouse = item.Warehouse,
MinimumStock = item.MinimumStock,
MaximumStock = item.MaximumStock,
StockForNow = item.StockForNow,
CoilWidth = item.CoilWidth,
SheetCoilLength = item.SheetCoilLength,
MaterialThickness = item.MaterialThickness
});
e.Result = allStock.ToArray();
}
}
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.prgStockProgress.Value = e.ProgressPercentage;
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
dgSysproStock.ItemsSource = (AllStock[])e.Result;
dgSysproStock.IsEnabled = true;
}
}
公共部分类pgSysproStock:Window
{
公共pgSysproStock()
{
初始化组件();
SysproStock.WindowState=WindowState.Normal;
dgSysproStock.IsEnabled=false;
worker.DoWork+=worker\u DoWork;
worker.RunWorkerCompleted+=worker\u RunWorkerCompleted;
worker.WorkerReportsProgress=true;
worker.ProgressChanged+=worker\u ProgressChanged;
worker.RunWorkerAsync();
}
private readonly BackgroundWorker worker=new BackgroundWorker();
私有异步void worker_DoWork(对象发送方,DoWorkEventArgs e)
{
使用(TruckServiceClient TSC=new TruckServiceClient())
{
List allStock=新列表();
this.Dispatcher.Invoke((操作)(()=>
{
prgStockProgress.Visibility=可见性.Visibility;
}));
foreach(wait TSC.GetSysproStockAsync()中的变量项)
allStock.Add(新的allStock)
{
Id=项目Id,
StockCode=item.StockCode,
描述=项目。描述,
ConvFactAltUom=item.ConvFactAltUom,
ConvMulDiv=item.ConvMulDiv,
convfactothoom=item.convfactothoom,
MulDiv=item.MulDiv,
质量=项目质量,
更新的供应商=物料。更新的供应商,
CycleCount=item.CycleCount,
ProductClass=item.ProductClass.ToString(),
单位成本=项目。单位成本,
折扣=物品。折扣,
仓库=项目。仓库,
最小库存=物料。最小库存,
MaximumStock=item.MaximumStock,
StockForNow=item.StockForNow,
CoilWidth=item.CoilWidth,
SheetCoillLength=项目。SheetCoillLength,
材料厚度=项目。材料厚度
});
e、 结果=allStock.ToArray();
}
}
私有void worker\u ProgressChanged(对象发送方,ProgressChangedEventArgs e)
{
this.prgStockProgress.Value=e.ProgressPercentage;
}
私有void worker\u RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
dgSysproStock.ItemsSource=(AllStock[])e.Result;
dgSysproStock.IsEnabled=true;
}
}
EDIT:我还从编码中的方法中删除了async
&wait
,但数据似乎仍然没有通过
我在这里添加了一个断点:
foreach(wait TSC.GetSysproStockAsync()中的var项)
,我无法通过TSC.GetSysproStock())
code。为什么要这样做?这不是BackgroundWorker的使用方式。尝试将数据传递到RunWorkerCompleted事件处理程序,并从那里更新UI
删除此项:
this.Dispatcher.Invoke((Action)(() =>
{
dgSysproStock.ItemsSource = (allStock.ToArray());
dgSysproStock.IsEnabled = true;
}));
在DoWork事件处理程序中,将结果设置为数据:
e.Result = allStock.ToArray();
然后在RunWorkerCompleted事件处理程序中:
dgSysproStock.ItemsSource = (AllSTock[])e.Result;
dgSysproStock.IsEnabled = true;
正确使用异步/等待:
public pgSysproStock()
{
InitializeComponent();
SysproStock.WindowState = WindowState.Normal;
this.UpdateStockAsync();
}
private async void UpdateStockAsync()
{
dgSysproStock.IsEnabled = false;
using (TruckServiceClient TSC = new TruckServiceClient())
{
var allStock = await TSC.GetSysproStockAsync().ToArray();
dgSysproStock.ItemsSource = allStock.Select(item =>
new AllStock
{
Id = item.Id,
StockCode = item.StockCode,
Description = item.Description,
ConvFactAltUom = item.ConvFactAltUom,
ConvMulDiv = item.ConvMulDiv,
ConvFactOthUom = item.ConvFactOthUom,
MulDiv = item.MulDiv,
Mass = item.Mass,
Updated_Supplier = item.Updated_Supplier,
CycleCount = item.CycleCount,
ProductClass = item.ProductClass.ToString(),
UnitCost = item.UnitCost,
Discount = item.Discount,
Warehouse = item.Warehouse,
MinimumStock = item.MinimumStock,
MaximumStock = item.MaximumStock,
StockForNow = item.StockForNow,
CoilWidth = item.CoilWidth,
SheetCoilLength = item.SheetCoilLength,
MaterialThickness = item.MaterialThickness
}).ToArray();
dgSysproStock.IsEnabled = true;
}
}
这是阻止UI的操作:
dgSysproStock.ItemsSource=(allStock.ToArray())代码>。不能将异步/等待与后台工作程序混合使用<代码>工作者工作
不能是异步的。我想说的是,扔掉BGW,单独使用async await。乍一看,在BackgroundWorker中使用async/await似乎是错误的。@Sriram Sakthivel-谢谢您的评论!:)如果我删除BackgroundWorker
我将无法使用我的UI,因为当我从WCF服务加载数据时,它将被禁用。如果您正确使用async/Wait,则不需要BackgroundWorker。await关键字会导致方法执行在多个线程之间分割,而方法的其余部分则充当回调。感谢您的回答和努力D我已经按照您的建议更新了代码,现在我可以使用我的所有UI元素(谢谢),但由于某些原因,数据似乎没有加载到我的datagrid中。问题可能出在e.Result=allStock.ToArray()代码>在我的嫁妆活动结束时?再次感谢你的第二个答案,格伦。数据加载与您提供的新编码很好,但我回到原点,所有UI仍然处于禁用/无响应状态:(但感谢您尝试帮助我。)在我做了一些研究之后,我会去问一个关于这个的新问题。我认为问题可能是GetSysproStockAsync使用yield关键字返回迭代器。尝试添加我更新的答案中的.ToArray(),看看这是否有帮助。嗨,格伦var allStock=wait TSC.GetSysproStockAsync().ToArray()代码>告诉我错误:不包含“ToArray”的定义,也没有扩展方法“ToArray”。您可能需要将“using System.Linq;”添加到代码文件中