PDA

View Full Version : عدم دسترسی به کنترل ها در تابع مربوط به Thread



elderado
جمعه 20 دی 1392, 00:35 صبح
با سلام و خسته نباشید
دوستان من یک تابع دارم و اون رو با ترد انجام میدم. به دلیل حجم بالای کاری که انجام میده
اما توی اون تابع هنگام استفاده از کنترل هایی که روی فرم گذاشتم یک پیغام خطا ظاهر میشه
میشه لطفا راهنمایی کنید ، چیکار باید بکنم؟
اینم متن پیغامی که میده:

Cross-thread operation not valid: Control 'listBox1' accessed from a thread other than the thread it was created on.

esafb52
جمعه 20 دی 1392, 00:50 صبح
BeginInvoke((MethodInvoker)delegate
{
//code

});

elderado
جمعه 20 دی 1392, 00:52 صبح
ممنونم دوست عزیز لطف کردی
الان مشکل بر طرف شد
ولی وقتی که داره اجرا میشه دیگه فرم در دسترس نیست
و وقتی روی فرم کلیک میکنم هنگ میکنه
مشکل کجاست؟

esafb52
جمعه 20 دی 1392, 01:39 صبح
از بک گراند ورکر استفاده کن خیلی سادهتر هست شما توضیح بشتر و کدهایی رو که نوشتین بذارین

elderado
جمعه 20 دی 1392, 12:47 عصر
الان وقتی که اجرا میشه فرم در دسترس نیست
بعد از مدتی یه پیغام خطا هم نمایش داده میشه که کل برنامه متوقف میشه
اینم کد با بک گراند ورکر:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
BeginInvoke((MethodInvoker)delegate
{
FolderBrowserDialog openfile = new FolderBrowserDialog();
if (openfile.ShowDialog() == DialogResult.OK)
{
DirectoryInfo dr = new DirectoryInfo(openfile.SelectedPath);
var directories = dr.GetDirectories();
int cc = 0, kh = 0;
listBox1.Items.Clear();
foreach (var directory in directories)
{

ListAllFiles(directory.FullName);
c = listBox1.Items.Count;
}
// listBox2.Items.Clear();

for (int i = 0; i < c; i++)
{
pro();
// progressBar1.Visible = true;
// progressBar1.Maximum = c;
// progressBar1.Minimum = 0;
// progressBar1.Step = 1;
byte[] jalal = null;
FileInfo fi = new FileInfo(listBox1.Items[i].ToString());
FileStream fs = new FileStream(listBox1.Items[i].ToString(), FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
long totalbytes = new FileInfo(listBox1.Items[i].ToString()).Length;
jalal = br.ReadBytes((Int32)totalbytes);
fs.Close();
fs.Dispose();
br.Close();
byte[] bytes = File.ReadAllBytes(listBox1.Items[i].ToString());
SqlParameter fileP = new SqlParameter("@file", SqlDbType.VarBinary);
fileP.Value = bytes;
SqlParameter name = new SqlParameter("@pname", SqlDbType.NVarChar);
name.Value = fi.Name;
SqlParameter add = new SqlParameter("@padd", SqlDbType.NVarChar);
add.Value = listBox1.Items[i].ToString();
SqlCommand myCommand = new SqlCommand();
myCommand.Parameters.Add(fileP);
myCommand.Parameters.Add(name);
myCommand.Parameters.Add(add);
SqlConnection conn = new SqlConnection(@"Data Source=.;Initial Catalog=pdf;Integrated Security=True");
if (conn.State != ConnectionState.Open)
conn.Open();
myCommand.Connection = conn;
myCommand.CommandText = "spPdfInsert";
myCommand.CommandType = CommandType.StoredProcedure;
// progressBar1.PerformStep();

Thread.Sleep(50);
try
{
myCommand.ExecuteNonQuery();

}
catch
{
kh++;
eror += this.listBox1.Items[i].ToString() + "\r\n";
}

conn.Close();
cc++;
}
// conn.Close();
// progressBar1.Visible = false;
MessageBox.Show("All files= " + cc.ToString());
MessageBox.Show("error: " + kh.ToString());
listBox1.Items.Clear();
if (kh > 0)
{
Form2 f = new Form2();
f.Show();
}
}
});
}
catch { }

و این هم پیغام خطای جدید:
"The CLR has been unable to transition from COM context 0x52dd08 to COM context 0x52de78 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations"

esafb52
جمعه 20 دی 1392, 13:20 عصر
دوست عزیز کد نویسیت خیلی بده شما به تعداد اون حلقه داری آبجکت ایجاد میکنی بگو دقیق میخوای چکار کنی اون فایل ها رو میخوای تو دیتابیس درج کنی

elderado
جمعه 20 دی 1392, 13:32 عصر
آره
میخوام اون فایل ها رو توی پایگاه درج کنم

esafb52
جمعه 20 دی 1392, 13:38 عصر
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SQLite;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Windows.Forms;

namespace danshjo
{
public partial class frmmain : Form
{

//تعریف متغیر ها بصورت سراسری در برنامه و ساختن نمونه از کلاس ها
private readonly PersianCalendar pc = null;
private BackUpAndRestore backUpwork = null;
private int count = 0;
private DataTable dt = null;
private FolderBrowserDialog folderBrowserDialog = null;
private SQLiteCommand cmd = null;
private SQLiteConnection con = null;


public frmmain()
{
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
pc=new PersianCalendar();
dt = new DataTable();
}

private void RowNumber()
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
row.HeaderCell.Value = (row.Index + 1).ToString();

}
dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisp layedHeaders;
dataGridView1.TopLeftHeaderCell.Value = " ردیف ";
dataGridView1.ColumnHeadersDefaultCellStyle.BackCo lor = Color.AntiqueWhite;
dataGridView1.EnableHeadersVisualStyles = false;
dataGridView1.Columns[1].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
dataGridView1.Columns[0].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
dataGridView1.Columns[0].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
dataGridView1.Columns[1].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
}

public DataTable LoadAll()
{
con = new SQLiteConnection("Data Source=picdb.sqlite;version=3");
string cmd = "select DISTINCT * from tblpic ORDER BY name";
using (SQLiteDataAdapter da = new SQLiteDataAdapter(cmd,con))
{
da.Fill(dt);
return dt;
}


}

private void frmmain_Load(object sender, EventArgs e)
{
dataGridView1.DataSource = LoadAll();
RowNumber();

}

private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{

}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
con = new SQLiteConnection("Data Source=picdb.sqlite;version=3");
cmd = new SQLiteCommand();
DirectoryInfo dir_info = new DirectoryInfo(folderBrowserDialog.SelectedPath);
List<string> file_list = new List<string>();
cmd.Connection = con;
con.Open();
BeginInvoke((MethodInvoker)delegate
{
progressBar1.Visible = true;
});

//*********** call main method*********************//
SearchDirectory(dir_info, file_list);
//***********main method*********************//

}

//******************************* main method******************************//
private void SearchDirectory(DirectoryInfo dir_info, List<string> file_list)
{
object bookname2;
try
{
foreach (DirectoryInfo subdir_info in dir_info.GetDirectories())
{
SearchDirectory(subdir_info, file_list);
}
}
catch
{
}
try
{
foreach (FileInfo item in dir_info.GetFiles("*.pdf", SearchOption.AllDirectories))
{
file_list.Add(item.FullName);
count++;
string mas = item.FullName;
string bookname = Path.GetFileNameWithoutExtension(mas);
bookname2 = bookname.PadLeft(100, ' ');
cmd.CommandText = "INSERT INTO tblpic (name,path) values(@1,@2)";
cmd.Parameters.AddWithValue("@1", bookname);
cmd.Parameters.AddWithValue("@2", mas);
cmd.ExecuteNonQuery();
backgroundWorker1.ReportProgress(count, bookname2);
if (count == 100)
{
count = 0;
}
}
}
catch
{

}
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
Text = e.UserState.ToString();
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
BeginInvoke((MethodInvoker)delegate
{
progressBar1.Value =100;
con.Close();
frmmain_Load(null, null);
Text = "کتابخانه دانشجو".PadLeft(50, ' ');
MessageBox.Show("کل کتاب ها با موفقیت درج شدند");
progressBar1.Visible = false;
progressBar1.Value = 0;

});
}

private void timer1_Tick(object sender, EventArgs e)
{
date.Text = "امروز : " + pc.GetYear(DateTime.Now)
+ "/" + pc.GetMonth(DateTime.Now).ToString("00")
+ "/" + pc.GetDayOfMonth(DateTime.Now).ToString("00")
+ " ساعت : "
+ pc.GetHour(DateTime.Now).ToString("00") + ":"
+ pc.GetMinute(DateTime.Now).ToString("00") + ":"
+ pc.GetSecond(DateTime.Now).ToString("00");
}

private void frmmain_FormClosing(object sender, FormClosingEventArgs e)
{
if (
MessageBox.Show("آیا قصد خروج از برنامه را دارید", "خروج", MessageBoxButtons.OKCancel,
MessageBoxIcon.Question) == DialogResult.OK)
{
e.Cancel = false;
}
else
{
e.Cancel = true;
}
}

private void تهیهپیشتیبانToolStripMenuItem_Click(ob ject sender, EventArgs e)
{
backUpwork= new BackUpAndRestore();
backUpwork.CurrentDbPath = Environment.CurrentDirectory + "\\picdb.sqlite";
backUpwork.BackUp();
}

private void عملیاتپشتیبانیToolStripMenuItem_Clic k(object sender, EventArgs e)
{

}

private void بازگردانیپشتیبانToolStripMenuItem_ Click(object sender, EventArgs e)
{
backUpwork = new BackUpAndRestore();
backUpwork.CurrentDbPath = Environment.CurrentDirectory + "\\picdb.sqlite";
backUpwork.Restore();
}

private void درجبهصورتگروهیToolStripMenuItem_Clic k(object sender, EventArgs e)
{
using ( folderBrowserDialog = new FolderBrowserDialog())
{
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
backgroundWorker1.RunWorkerAsync();
progressBar1.Visible = true;
}
}

}

private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
if (dataGridView1.Rows.Count > 1)
{
string masirbook;
try
{
masirbook = dataGridView1.CurrentRow.Cells["path"].Value.ToString();
Process.Start(masirbook);
}
catch (SystemException exception)
{
MessageBox.Show("کتاب پیدا نشد!!!!");
MessageBox.Show(exception.Message);
}
}
else
{
MessageBox.Show("!هیچ موردی برای نمایش وجود ندارد!", "توجه");
}
}

private void textBox1_TextChanged(object sender, EventArgs e)
{
if (textBox1.Text!=string.Empty)
{
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
if (dataGridView1.Rows[i].Cells[0].Value.ToString() == textBox1.Text)
{
dataGridView1.Rows[i].Selected = true;
dataGridView1.FirstDisplayedScrollingRowIndex = i;
}
}
}
else
{
dataGridView1.ClearSelection();
dataGridView1.FirstDisplayedScrollingRowIndex = 0;
}
}

private void frmmain_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char) 13)
{
dataGridView1_CellDoubleClick(null,null);
}
}

private void دربارهماToolStripMenuItem_Click(object sender, EventArgs e)
{


}

private void mnuexit_Click(object sender, EventArgs e)
{
Application.Exit();
}

private void حذفکلاطلاعاتToolStripMenuItem_Click(ob ject sender, EventArgs e)
{

if (
MessageBox.Show("آیا قصد حذف کل اطلاعات را دارید", "خروج", MessageBoxButtons.OKCancel,
MessageBoxIcon.Question) == DialogResult.OK)
{
string s = "DELETE FROM tblpic";
con = new SQLiteConnection("Data Source=picdb.sqlite;version=3");
using (cmd = new SQLiteCommand(s, con))
{
con.Open();
cmd.ExecuteNonQuery();
con.Clone();
}
MessageBox.Show("با موفقیت انجام شد");
Application.Restart();
}



}

private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text != string.Empty)
{
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
if (dataGridView1.Rows[i].Cells[0].Value.ToString().StartsWith(textBox1.Text, StringComparison.OrdinalIgnoreCase))
{
dataGridView1.Rows[i].Selected = true;
dataGridView1.FirstDisplayedScrollingRowIndex = i;
}
}
}
else
{
dataGridView1.ClearSelection();
dataGridView1.FirstDisplayedScrollingRowIndex = 0;
}
}
}
}

esafb52
جمعه 20 دی 1392, 13:41 عصر
کدی رو که بالا گذاشتم در اصل برای مدیریت یه عکاسی هست که من تغییر دادم و برای کتابخانه pdf هم ازش استفاده میکنم به متد های درج اش و نیو کردن شی ها دقت کنین

elderado
جمعه 20 دی 1392, 13:54 عصر
این کد رو اینجوریش کردم
اینجوری خوبه؟

BeginInvoke((MethodInvoker)delegate
{
FolderBrowserDialog openfile = new FolderBrowserDialog();
if (openfile.ShowDialog() == DialogResult.OK)
{
DirectoryInfo dr = new DirectoryInfo(openfile.SelectedPath);
var directories = dr.GetDirectories();
int cc = 0, kh = 0;
listBox1.Items.Clear();
foreach (var directory in directories)
{

ListAllFiles(directory.FullName);
c = listBox1.Items.Count;
}
// listBox2.Items.Clear();
FileInfo fi;
FileStream fs;
BinaryReader br;
SqlParameter fileP;
SqlParameter name;
SqlParameter add;
SqlCommand myCommand;
SqlConnection conn;
for (int i = 0; i < c; i++)
{
//pro();
progressBar1.Visible = true;
progressBar1.Maximum = c;
progressBar1.Minimum = 0;
progressBar1.Step = 1;
byte[] jalal = null;
fi = new FileInfo(listBox1.Items[i].ToString());
fs = new FileStream(listBox1.Items[i].ToString(), FileMode.Open, FileAccess.Read);
br = new BinaryReader(fs);
long totalbytes = new FileInfo(listBox1.Items[i].ToString()).Length;
jalal = br.ReadBytes((Int32)totalbytes);
fs.Close();
fs.Dispose();
br.Close();
byte[] bytes = File.ReadAllBytes(listBox1.Items[i].ToString());
fileP = new SqlParameter("@file", SqlDbType.VarBinary);
fileP.Value = bytes;
name = new SqlParameter("@pname", SqlDbType.NVarChar);
name.Value = fi.Name;
add = new SqlParameter("@padd", SqlDbType.NVarChar);
add.Value = listBox1.Items[i].ToString();
myCommand = new SqlCommand();
myCommand.Parameters.Add(fileP);
myCommand.Parameters.Add(name);
myCommand.Parameters.Add(add);
conn = new SqlConnection(@"Data Source=.;Initial Catalog=pdf;Integrated Security=True");
if (conn.State != ConnectionState.Open)
conn.Open();
myCommand.Connection = conn;
myCommand.CommandText = "spPdfInsert";
myCommand.CommandType = CommandType.StoredProcedure;
progressBar1.PerformStep();

// Thread.Sleep(50);
try
{
myCommand.ExecuteNonQuery();

}
catch
{
kh++;
eror += this.listBox1.Items[i].ToString() + "\r\n";
}

conn.Close();
cc++;
}
// conn.Close();
progressBar1.Visible = false;
progressBar1.Value = 0;
MessageBox.Show("All files= " + cc.ToString());
MessageBox.Show("error: " + kh.ToString());
listBox1.Items.Clear();
if (kh > 0)
{
Form2 f = new Form2();
f.Show();
}
return;
}
});

ولی بازم اون پیغام خطا ظاهر میشه

esafb52
جمعه 20 دی 1392, 14:16 عصر
دوست عزیز
شما مگه قرار چند بار پروگرس بار رو ظاهر کنید که اون رو تو حلقه میذارین یا این قد کلاس رو چرا با هر اجرای حلقه نیو میکنی به کدهایی که گذاشتم دقت کن اون قسمت دیلیگیت فقط برای اشیایی هست که از اون ترد بهش دسترسی نداری نه اینکه همه کدهات رو تو اون بذاری!!!
بای

elderado
شنبه 21 دی 1392, 14:47 عصر
عزیز همه اینا مال اینه که بلد نیستم
اگه بلد بودم که این سوالا رو اینجا نمی پرسیدم
این کد هم فقط یه دونه مسیج باکس بهش اضافه کردم که هر 400 تا فایل یک بار نمایش داده میشه
دیگه اون ارور نمیاد.

abdolwahab
شنبه 21 دی 1392, 15:06 عصر
کار آسونتر

تو تابع سازنده فرمی که خطا رو میده

mainfrm.CheckForIllegalCrossThreadCalls = false

elderado
شنبه 21 دی 1392, 19:46 عصر
با این کد هم جواب نداد ، بازم همون پیغام اومد

amir001
یک شنبه 22 دی 1392, 17:07 عصر
با CheckForIllegalCrossThreadCalls = false باید مشکلت حل بشه
اون خطای دومی که گذاشتی مربوط به ترد ها نمیشه و برای کد خاصی از برنامه ات هست. باید ببینی کدوم قسمت برنامه ات این خطا را تولید میکنه.

elderado
پنج شنبه 26 دی 1392, 11:59 صبح
با سلام مجدد

The CLR has been unable to transition from COM context 0x52dd08 to COM context 0x52de78 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations


این مشکل حل شد. طبق حرف همین پیغام خطا ، برای درج کردن هر 400 فایل یک مسیج باکس گذاشتم.
الان برنامه داره براحتی کار میکنه و هیچ مشکلی هم نداره