[Windows表格应用程序& .NET 4.0]
我需要执行返回对象(类列表或简单类)的数据库访问方法。
此外,我还需要在主线程初始化时打开响应的表单。
我需要在单独的线程上运行它们,以保持用户界面的响应性,当然还能够将结果传递回主线程以进行UI更新。
我一直在阅读有关各种方法的书籍。
我明白我的工作可以通过以下方式完成:
我应该深入研究哪一个?
更新:使用建议的Task类我使用这个来获得交叉线程安全的错误:
private void BtnCheckClick(object sender, EventArgs e)
{
var itm = Task<JDEItemLotAvailability>.Factory.StartNew(() =>
Dal.GetLotAvailabilityF41021(
txtLot.Text,
cmbMcu.SelectedItem.ToString(),
cmbLocn.SelectedItem.ToString())
);
lblDescriptionValue.Text = itm.Result.Description;
lblItemCodeValue.Text = itm.Result.Code;
lblQuantityValue.Text = itm.Result.AvailableQuantity.ToString();
LotFocus(true);
}
在上面的例子中,我在cmbMcu控件中得到异常而不是txtLot。
答案 0 :(得分:1)
我已经使用Thread完成了很多项目,但是Task应该更容易使用。
这是演示如何使用Threads进行异步操作。
这是将数据返回给ui的类:
public class MyAsyncClass
{
public delegate void NotifyComplete(DataSet data);
public event NotifyComplete NotifyCompleteEvent;
//Starts async thread...
public void Start()
{
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(DoSomeJob));
t.Start();
}
void DoSomeJob()
{
//just wait 5 sec for nothing special...
System.Threading.Thread.Sleep(5000);
if (NotifyCompleteEvent != null)
{
//TODO: fill your data...
DataSet ds = new System.Data.DataSet();
NotifyCompleteEvent(ds);
}
}
}
这是ui实施:
MyAsyncClass myClass = null;
private void button2_Click(object sender, EventArgs e)
{
myClass = new MyAsyncClass();
myClass.NotifyCompleteEvent += new MyAsyncClass.NotifyComplete(myClass_NotifyCompleteEvent);
//here I start the job inside working class...
myClass.Start();
}
//here my class is notified from working class when job is completed...
delegate void myClassDelegate(DataSet data);
void myClass_NotifyCompleteEvent(DataSet data)
{
if (this.InvokeRequired)
{
Delegate d = new myClassDelegate(myClass_NotifyCompleteEvent);
this.Invoke(d, new object[] { data });
}
else
{
//TODO: show your data
MessageBox.Show("Data retrieved!");
}
}
答案 1 :(得分:1)
我会使用 Task
类,它很容易同步它,它已经为返回对象提供了支持。
var task = Task.Factory.StartNew(
() => GetDatabaseData(someArguments),
TaskCreationOptions.LongRunning);
// Example method
public DataSet GetDatabaseData(object args) { ... }
这会告诉 scheduler 创建并开始一个新任务并给它一个暗示,如果调度程序不使用线程池线程可能是个好主意使用线程池。无论如何,您现在可以决定如何同步。
例如,要实现与Gregor Primar的答案类似的行为,您可以使用 ContinueWith
方法设置延续,如下所示,
task.ContinueWith(oldTask => ProcessReturnedData(oldTask.Result));
// Example method
public IEnumerable<SomeEntity> ProcessReturnedData(DataSet data) { ... }
将在ProcessReturnedData
对象执行完毕后调度task
方法。请注意,即使task
由于某种原因失败,也会调用此方法,因此它可能不总是一个好的解决方案 - 或者您必须在提供的委托中进行一些检查。
如果你想在主线程上进行非阻塞等待并在那里使用返回的对象,你只需使用 Wait
方法。
task.Wait(); // Makes current thread wait until the task is comnpleted.
DataSet result = task.Result; // Accessing the result object.