PDA

View Full Version : حرفه ای: تبدیل یک تابع به صورت async



رامین مرادی
شنبه 16 دی 1396, 15:41 عصر
وقت بخیر دوستان من تابع زیر رو دارم به نظرتون میشه اینو بصورت همزمان اجراش کرد؟؟ در صورت امکان همراه با توضیحات بگید
این کد اصلی خودمه


public void ShowAll()
{
AsansorDA _AsansorDA = new AsansorDA();
table = _AsansorDA.SelectAll();
dgv1.DataSource = table;

}



که به این صورت نوشتم


private async Task ShowAll()
{
await Task.Run(() =>
{
AsansorDA _AsansorDA = new AsansorDA();
table = _AsansorDA.SelectAll();
dgv1.DataSource = table;
});
}



که به Run گیر میده یعنی کلا برای تسک چنین متدی نیست.
:افسرده:

ramtinak
شنبه 16 دی 1396, 18:02 عصر
سلام،
کلاس Task از دات نت 4.0 به بعد اضافه شده، پس شما کم کم باید Targetـه دات نت پروژتون روی این نسخه باشه تا بتونید از این کلاس استفاده کنید.
--------------------------------------
جای Run
از Task.Factory هم میتونید استفاده کنید. من یه تابع دارم که در ورودیش یک Action میگیره:
static public async Task RunAsync(Action action) {
try
{
await Task.Factory.StartNew(() =>
{
try
{
action?.Invoke();
}
catch (Exception ex)
{
ex.Exception("RunAsyncEX");
}
}, new System.Threading.CancellationTokenSource().Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
catch (Exception ex)
{
ex.Exception("RunAsync");
}
}

شما می تونید کدتون به صورت زیر با این کد ادغام کنید:
await RunAsync(()=>{
AsansorDA _AsansorDA = new AsansorDA();
table = _AsansorDA.SelectAll();
dgv1.DataSource = table;
});

اما ممکنه این کد، خطای Marshal Called بده، و دلیلش هم اینه که شما دارید توی این کد به UI پارامتر میفرستید (dgv1.DataSource...)
حقیقتا زیاد وینفرم کار نکردم اما فکر کنم چون ورودیش Action هست به کدتون گیر نده
--------------
بروز رسانی:
میشه تابع رو به صورت بازگشتی هم نوشت:

public class MyTokenList : List<MToken> {
public async Task<Object> SelectAll()
{
await Task.Factory.StartNew(() =>
{
try
{
AsansorDA _AsansorDA = new AsansorDA();
table = _AsansorDA.SelectAll();
return table;
}
catch (Exception ex)
{
ex.Exception("RunAsyncEX");
}
}, new System.Threading.CancellationTokenSource().Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);




return new Object();
}
}


جای Object که در تعریف تابع و آخر اون نوشته شده، تایپ SelectAll در کد _AsansorDA.SelectAll() قرار بدید.
واسه فراخونی هم کافیه بنویسید:

dgv1.DataSource = await SelectAll();
موفق باشید.

رامین مرادی
یک شنبه 17 دی 1396, 08:08 صبح
ممنون دوست عزیز.ولی کلا به تابع SelectAll() گیر میده
Error 5 Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?

فریم ورک پروژم هم 4 هست.
به await هم گیر میده
Error 2 The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.

به اکسپشن هم گیر میده. :عصبانی++:

danialafshari
یک شنبه 17 دی 1396, 09:33 صبح
ممنون دوست عزیز.ولی کلا به تابع SelectAll() گیر میده
Error 5 Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?

فریم ورک پروژم هم 4 هست.
به await هم گیر میده
Error 2 The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.

به اکسپشن هم گیر میده. :عصبانی++:

با سلام
ارور Error 5 Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?
طبق ارور دات نت تنظیم نیست و باید روی 4.5 به بعد قرار بدید
Error 2 The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
این خطا هم میگه بدلیل اینکه async ی وجود نداره await ی هم نخواهد بود.
یک مثال از async :

private Task<string> DoWork()
{
return Task.Run(() =>
{
System.Threading.Thread.Sleep(10000);
return "Done.";
});
}


private async void CallButton_Click(object sender, EventArgs e)
{
this.Text = await DoWork();
}

موفق باشید

رامین مرادی
یک شنبه 17 دی 1396, 10:05 صبح
با سلام
ارور Error 5 Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?
طبق ارور دات نت تنظیم نیست و باید روی 4.5 به بعد قرار بدید
Error 2 The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
این خطا هم میگه بدلیل اینکه async ی وجود نداره await ی هم نخواهد بود.
یک مثال از async :

private Task<string> DoWork()
{
return Task.Run(() =>
{
System.Threading.Thread.Sleep(10000);
return "Done.";
});
}


private async void CallButton_Click(object sender, EventArgs e)
{
this.Text = await DoWork();
}

موفق باشید

با این میشه به اشیایی مثل دیتا گرید دسترسی داشت؟

رامین مرادی
یک شنبه 17 دی 1396, 10:21 صبح
من با برداشتی که از حرفای شما دوستان داشتم اون کد رو تبدیل کردم به اینی که نوشتم. ولی به فراخوانی تابع گیر میده


public void ShowAll()
{
AsansorDA _AsansorDA = new AsansorDA();
table =await SelectAll();
dgv1.DataSource = table;

}

public async Task<DataTable> SelectAll()
{
await Task.Factory.StartNew(() =>
{
try
{
AsansorDA _AsansorDA = new AsansorDA();
table = _AsansorDA.SelectAll();
return table;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;

//ex.Exception("RunAsyncEX");
}
}, new System.Threading.CancellationTokenSource().Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
return new DataTable();
}



خطاش هم
Error 4 The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.

ali_md110
یک شنبه 17 دی 1396, 12:34 عصر
اگر برنامه شما تحت ویندوز و تک کاربره هست نیاز انچنانی به پیاده سازی متدهای async await نیست و میتونید کارهای طولانی مدت رو با backgrounworker پیاده کنید
ولی


return Task.Run(() =>


برای برنامه های تحت ویندوز میتوان استفاده کرد اما در سطح وب بکار نبرید این متدها به متدهای تقلبی یا Fake Async مشهور هستند




public async Task<DataTable> MyMetod()
{
return await Task.Run(() =>
{
return myvalues;

});
}




private async void _Click(object sender, EventArgs e)
{
await Task.Run(() => MyMetod());
}

رامین مرادی
یک شنبه 17 دی 1396, 12:53 عصر
اگر برنامه شما تحت ویندوز و تک کاربره هست نیاز انچنانی به پیاده سازی متدهای async await نیست و میتونید کارهای طولانی مدت رو با backgrounworker پیاده کنید
ولی


return Task.Run(() =>


برای برنامه های تحت ویندوز میتوان استفاده کرد اما در سطح وب بکار نبرید این متدها به متدهای تقلبی یا Fake Async مشهور هستند




public async Task<DataTable> MyMetod()
{
return await Task.Run(() =>
{
return myvalues;

});
}




private async void _Click(object sender, EventArgs e)
{
await Task.Run(() => MyMetod());
}


نه برنامه تو شبکه کار میکنه و تحت ویندوز و چندین کاربره هست. پس به نظرتون چیکار میشه کرد که مثلا فرم موقع باز شدن داده هارو لود کنه مثلا 1000 رکورد رو .تو روش معمولی مثلا فرم قبل باز شدن چندثانیه منتظر لود شدن داده میشه. اینو یه کاری بشه کرد که همزمان با لود فرم اصلی هم باز بشه

اینم نوشتم. ولی یه جای کار میلنگه و داده ها برگشت داده نمیشه



public void ShowAll()
{
AsansorDA _AsansorDA = new AsansorDA();
dgv1.DataSource = Task.Run(() => MyMetod());
}
public async Task<DataTable> MyMetod()
{
return await Task.Run(() =>
{
AsansorDA _AsansorDA = new AsansorDA();
return _AsansorDA.SelectAll();
});
}

رامین مرادی
یک شنبه 17 دی 1396, 13:19 عصر
با بک گراند ورکر نوشتم.اما نمدونم کارم اصولیه یا نه:افسرده:



public void ShowAll()
{
_worker1.RunWorkerAsync();

}
private void _worker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{

dgv1.DataSource = table;

}
private void worker1_DoWork(object sender, DoWorkEventArgs e)
{
AsansorDA _AsansorDA = new AsansorDA();
table = _AsansorDA.SelectAll();
}

barnamenevisjavan
دوشنبه 18 دی 1396, 16:09 عصر
وقت بخیر دوستان من تابع زیر رو دارم به نظرتون میشه اینو بصورت همزمان اجراش کرد؟؟ در صورت امکان همراه با توضیحات بگید
این کد اصلی خودمه


public void ShowAll()
{
AsansorDA _AsansorDA = new AsansorDA();
table = _AsansorDA.SelectAll();
dgv1.DataSource = table;

}



که به این صورت نوشتم


private async Task ShowAll()
{
await Task.Run(() =>
{
AsansorDA _AsansorDA = new AsansorDA();
table = _AsansorDA.SelectAll();
dgv1.DataSource = table;
});
}



که به Run گیر میده یعنی کلا برای تسک چنین متدی نیست.
:افسرده: به این صورت باید استفاده کنید
public async static Task<List<Student>> GetAllStudentsAsync()

{


MyDatabaseEntities db = new MyDatabaseEntities();


var query = from item in db.Students


select item;


return await query.ToListAsync();


}
بعدش برای فراخوانی تابع به این صورت عمل کنید

var query = GetAllStudentsAsync();

query.Wait();


List<Student> data = query.Result;


Console.WriteLine("Total Records in Students Table are:" + " " + data.Count);