如何在在WinFrom的DataGridView中做到数据持续动态加载而不卡死
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在在WinFrom的DataGridView中做到数据持续动态加载而不卡死相关的知识,希望对你有一定的参考价值。
1.在这个过程我用过好几种办法
(1)使用委托的办法,这个方法可以做到持续加载,但是效果不理想会卡死
(2)开启线程的方法,会造成卡死
(3)使用另一个窗体的线程做持续加载(子窗体),让子窗体作为一个中间件去通知dataGridView绑定数据,子窗体隐藏。从而可以使主窗体不用卡死 ,给用户造成一中假状态,卡死的是子窗体而已,并且做了隐藏。
2.截图如下
(3)代码如下
<1>借助了两个类:ComAsyncExecute.cs TSwitch.cs
<2>具体代码内容如下:
ComAsyncExecute.cs
using System;
using System.Threading;
using System.Windows.Forms;
namespace APIBigData.Helper.Tool
{
public class ComEventArgsBase
{
public Exception Error = null;
}
public class ComEventArgs<T> : ComEventArgsBase
{
public String ErrorInfo = "";
public T Result
{
get;
set;
}
}
public class ComEventArgs<T, TM> : ComEventArgs<T>
{
public TM Per1 = default(TM);
public ComEventArgs(TM per)
{
this.Per1 = per;
}
}
public class ComEventArgs<T, TM, TZ> : ComEventArgs<T, TM>
{
public TZ Per2 = default(TZ);
public ComEventArgs(TM per, TZ per2)
: base(per)
{
this.Per2 = per2;
}
}
public class ComAsyncOnceDrive
{
private void SetDataSource(Object ob, EexecuteState estare)
{
if (delSetData != null) { delSetData(ob, estare); }
}
private void SetDataSourceExtract(Object ob, EexecuteState estare)
{
if (delSetDataExtract != null) { delSetDataExtract(ob, estare); }
}
public TSwitch.Omnipotent<Object, EexecuteState> delSetData = null;
public TSwitch.Omnipotent<Object, EexecuteState> delSetDataExtract = null;
}
public enum EexecuteState : int
{
Start = 0,
Middle = 1,
End = 3,
}
/// <summary>
/// 通用异步工具
/// </summary>
/// <typeparam name="T"></typeparam>
public class ComAsync<T> where T : ComEventArgsBase
{
public delegate void CellProcedureArray(T ob);
private ComAsyncOnceDrive _onceder = null;
public ComAsyncOnceDrive GetOnceControl()
{
var z = new ComAsyncOnceDrive
{
delSetData = (e, m) =>
{
if (FinshOneceEexecute != null && _puiThread != null)
{
_puiThread.BeginInvoke(FinshOneceEexecute, new object[] { e, m });
}
}
};
this._onceder = z;
return z;
}
public ComAsyncOnceDrive GetOnceControlExtract()
{
var z = new ComAsyncOnceDrive
{
delSetDataExtract = (e, m) =>
{
if (FinshOneceEexecuteExtract != null && _puiThread != null)
{
_puiThread.BeginInvoke(FinshOneceEexecuteExtract, new object[] { e, m });
}
}
};
this._onceder = z;
return z;
}
CellProcedureArray _cellprocedureArrayAsync = null;
public delegate void DelcellFinsh(object sender, T e);
public DelcellFinsh EnevtcellFinsh = null;
public TSwitch.Omnipotent<Object, EexecuteState> FinshOneceEexecute = null;
public TSwitch.Omnipotent<Object, EexecuteState> FinshOneceEexecuteExtract = null;
private readonly Form _puiThread = null;
private T _data = null;
public ComAsync(Form fo)
{
_puiThread = fo;
}
public IAsyncResult AsynResult = null;
public bool IsUIfinsh
{
get { return AsynResult != null && AsynResult.IsCompleted; }
}
public ComAsync() { }
public void BindProcedure(T t, CellProcedureArray cell)
{
BindProcedure(cell, t);
}
public void BindProcedure(CellProcedureArray cell, T t)
{
if (_cellprocedureArrayAsync == null)
{
_cellprocedureArrayAsync = new CellProcedureArray(cell);
_data = t;
}
else
{
_cellprocedureArrayAsync = null;
_cellprocedureArrayAsync = new CellProcedureArray(cell);
_data = t;
}
}
//可用
public bool IsWiatUse
{
get { return !_isRun; }
}
private bool _isRun = false;
public void Run()
{
if (_isRun == false)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(RunProcedure), 0);
_isRun = true;
}
else
{
throw new Exception("客官别急,正在努力加载中");
}
}
public void RunProcedure(object ob)
{
AsynResult = null;
if (_cellprocedureArrayAsync == null) { throw new Exception("没有绑定函数,无法运行"); }
try
{
//执行
if (_cellprocedureArrayAsync != null) { _cellprocedureArrayAsync.Invoke(_data); }
}
catch (Exception ex)
{
_data.Error = ex;
}
//回调
//如果是UI线程
if (_puiThread != null && EnevtcellFinsh != null)
{
_puiThread.BeginInvoke(EnevtcellFinsh, new object[] { this, _data });
}
else
{
// ThreadPool.QueueUserWorkItem(new WaitCallback(CellNewThind), new ComEventArgs<T>(t, exTemp, RefParameter));
if (EnevtcellFinsh != null) { EnevtcellFinsh.Invoke(this, _data); }
}
// timeEnd = DateTime.Now;
_isRun = false;
}
private void CellNewThind(object ob)
{
}
}
}
TSwitch.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace APIBigData.Helper.Tool
{
/// <summary>
/// T类型和M类型的转换 或者 T与object 之间的转换,并提供了万能模板事件
/// </summary>
public class TSwitch
{
/// <summary>
/// 通用模板事件
/// </summary>
/// <typeparam name="A"></typeparam>
/// <param name="t"></param>
public delegate void Omnipotent<A >(A t);
public delegate void Omnipotent<A, B>(A t, B m);
public delegate void Omnipotent<A, B, C>(A t, B m, C z);
public delegate void Omnipotent<A, B, C,D>(A t, B m, C z,D d);
public delegate void Omnipotent<A, B, C, D, E>(A t, B m, C z, D d ,E e);
public delegate void Omnipotent<A, B, C, D, E, F>(A t, B m, C z, D d, E e ,F f);
public delegate Object OmnipotentTo<A>(A t);
public delegate Object OmnipotentTo<A, B>(A t, B m);
public delegate Object OmnipotentTo<A, B, C>(A t, B m, C z);
public delegate Object OmnipotentTo<A, B, C, D>(A t, B m, C z, D d);
public delegate Object OmnipotentTo<A, B, C, D, E>(A t, B m, C z, D d, E e);
public delegate Object OmnipotentTo<A, B, C, D, E, F>(A t, B m, C z, D d, E e, F f);
public delegate bool OmnipotentDispose<A>(A t);
public delegate bool OmnipotentDispose<A, B>(A t, B m);
public delegate bool OmnipotentDispose<A, B, C>(A t, B m, C z);
public delegate bool OmnipotentDispose<A, B, C, D>(A t, B m, C z, D d);
public delegate bool OmnipotentDispose<A, B, C, D, E>(A t, B m, C z, D d, E e);
public delegate bool OmnipotentDispose<A, B, C, D, E, F>(A t, B m, C z, D d, E e, F f);
/// <summary>
/// 模板类型数组转换 T --> M
/// </summary>
/// <typeparam name="T">源类型</typeparam>
/// <typeparam name="M">目标类型</typeparam>
/// <param name="source">源数据 T</param>
/// <param name="TypeTransition">转换事件</param>
/// <returns>目标类型M</returns>
public static M TTransitionT<T,M>(T source , OmnipotentTo<T> TypeTransition)
{
return (M)TypeTransition(source);
}
/// <summary>
/// 模板类型数组转换 T[] --> M[]
/// </summary>
/// <typeparam name="T">源类型</typeparam>
/// <typeparam name="M">目标类型</typeparam>
/// <param name="source">源数据数组 T[]</param>
/// <param name="TypeTransition">转换事件</param>
/// <returns>目标类型数组 M[]</returns>
public static M[] TTransitionT<T, M>(T[] source, OmnipotentTo<T> TypeTransition)
{
M[] Datasz = new M[source.Count()];
int i = 0;
foreach (T t in source)
{
Datasz[i] = TTransitionT<T, M>(t, TypeTransition);
i++;
}
return Datasz;
}
/// <summary>
/// 模板类型数组转换 T[] --> Object[]
/// </summary>
/// <typeparam name="T">被转换的类型</typeparam>
/// <param name="ts">参数数组 ,T[]</param>
/// <returns>object数组</returns>
public static object[] ObsTransition<T>(T[] ts)
{
List<object> obs = new List<object>();
foreach (T t in ts)
{
obs.Add(t);
}
return obs.ToArray();
}
/// <summary>
/// 模板类型数组转换 Object[] --> T[]
/// </summary>
/// <typeparam name="T">想要输出的类型</typeparam>
/// <param name="obs">参数数组 ,Object[]</param>
/// <returns>T[]输出的数组</returns>
public static T[] TsTransition<T>(Object[] obs)
{
List<T> ts = new List<T>();
foreach (object ob in obs)
{
ts.Add((T)ob);
}
return ts.ToArray();
}
public static T[] TsTransition<T>(IList list)
{
T[] ts = new T[list.Count];
for(int i = 0; i <list.Count;i++)
{
ts[i] = (T)list[i];
}
return ts;
}
/// <summary>
/// 万能数据筛选/处理, 事件返回值等于 true 则添加
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="ts"></param>
/// <param name="delT"></param>
/// <returns></returns>
public static T[] DataDispose<T>(T[] ts, OmnipotentDispose<T> delT)
{
if(ts == null) {return null;}
List<T> listT = new List<T>();
for (int i = 0; i < ts.Length; i++)
{
if (delT(ts[i])) { listT.Add(ts[i]); }
}
return listT.ToArray();
}
/// <summary>
/// 万能数据筛选
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="ts"></param>
/// <param name="delT"></param>
/// <returns></returns>
public static T[] DataDispose<T>(T[] ts, Omnipotent<T> delT)
{
if (ts == null) { return null; }
List<T> listT = new List<T>();
for (int i = 0; i < ts.Length; i++)
{
listT.Add(ts[i]);
}
return listT.ToArray();
}
}
}
查询事件下的代码: 调用Serarch()
private Waiting _wait = null;
//原来调用具有返回值的方法的声明
// private ComAsync<ComEventArgs<List<Website>, QueryCriteria>> _comGetSearchWork = null;
private ComAsync<ComEventArgsBase> _comGetSearchWork = null;
public void Search(QueryCriteria query)
{
//原来调用具有返回值方法的判断
// if (_comGetSearchWork == null) { _comGetSearchWork = new ComAsync<ComEventArgs<List<Website>, QueryCriteria>>(this); }
if (_comGetSearchWork == null) { _comGetSearchWork = new ComAsync<ComEventArgsBase>(this); }
this.dataGridView.Rows.Clear();
this.dataGridViewExtract.Rows.Clear();
if (checkLog.CheckState == CheckState.Checked)
email = new ExtractEmail(query, new XmlHelper(DateTime.Now), new DataBindGridView(DataBind));
else email = new ExtractEmail(query, null, new DataBindGridView(DataBind));
//ExtractEmail email = new ExtractEmail(query, new XmlHelper(), new DataBindGridView(DataBind));
email.dri = _comGetSearchWork.GetOnceControl();
email.driExtract = _comGetSearchWork.GetOnceControlExtract();
//原来调用有返回值的方法
//_comGetSearchWork.BindProcedure(new ComEventArgs<List<Website>, QueryCriteria>(query), ob =>
//{
// ob.Result=email.Result_Email();
//});
_comGetSearchWork.BindProcedure(new ComEventArgsBase(), ob =>
{
email.Result_Emails();
});
_comGetSearchWork.FinshOneceEexecute = (e, m) =>
{
Website data = e as Website;
//这个方法是操作dataGrivdView的方法 有数据绑定 显示指定列 根据需求具体操作
DataBind(new List<Website>(new Website[] { data }));
};
_comGetSearchWork.FinshOneceEexecuteExtract = (e, m) =>
{
Website data = e as Website;
//这个方法是操作dataGrivdView的方法 有数据绑定 显示指定列根据需求具体操作
DataBindExtract(new List<Website>(new Website[] { data }));
};
_comGetSearchWork.EnevtcellFinsh = (sen, e) =>
{
try
{
if (e.Error != null)
{
//执行错误
_wait.Close();
MessageBox.Show(e.Error.Message);
return;
}
}
catch (Exception)
{
// throw;
}
finally
{
_wait.Close();
this.btnSearchClick.Enabled = true;
if (this.dataGridView.Rows.Count > 0) this.btnExportExcel.Enabled = true;
//SetGridView();
// string time = ThanTime(timeStart, _comGetSearchWork.timeEnd);
MessageBox.Show("查询完毕", "温馨提示");
this.searchLab.Text = "搜索完成";
this.pos = 0;
}
};
_wait = new Waiting();
_comGetSearchWork.Run();
// Location = new Point(_wait.Location.X-Size.Width, _wait.Location.Y - Size.Height);
// _wait.ShowDialog();
_wait.MdiParent = this;
_wait.StartPosition = FormStartPosition.CenterScreen;
_wait.Show();
_wait.Hide();
}
操作数据类:
在这个类中我们首先要声明一个:
然后添加:
这里我是把一个集合通过他绑定到dataGridView
最后附一张图片,是关键代码,具体的用法研究下,如有不对,还希望大家指正
至此整个过程完成 ,这个方法我也是从大神那里得到的 .感谢帮助我各位,在这里我做一个总结,由于涉及到保密,未能过完整提供源码。
以上是关于如何在在WinFrom的DataGridView中做到数据持续动态加载而不卡死的主要内容,如果未能解决你的问题,请参考以下文章
c#winfrom中datagridview控件如何自定义一个datagridview的列。主要是想实现类似EXCEL中的合并单元格
winfrom datagridview如何给所有行的DataGridViewComboBoxCell都添加内容
winfrom datagridview中DataGridViewTextBoxColumn的联动处理
C# winfrom datagridview 如何为一列添加向下滚动条 请看清楚再回答!