|
You don't need to. As long as there is a single reference to any object, it will not be destroyed - that is one of the major advantages of managed code over unmanaged.
So:
frmMain:
Where myNewForm = new Where();
myNewForm.ShowDialog();
ArrayList myListOfBitsInFrmMain = myNewForm.myArrayListOfBits;
Where:
myArrayListOfBits = new ArrayList();
myArrayListOfBits.Add("Item1");
myArrayListOfBits.Add("Item2");
then "myListOfBitsInFrmMain" contains a reference to an ArrayList with two items. Unless "myListOfBitsInFrmMain" goes out of scope, or your frmMain instance is destroyed, the ArrayList will be available.
Did you know:
That by counting the rings on a tree trunk, you can tell how many other trees it has slept with.
|
|
|
|
|
Griff,
Thank for for your detailed explanation and example. What's even better is that I now have a better understanding of how the arrays work! I have changed the code accordingly and it works perfect. I have marked this as the correct answer. Best Regards, Pat
|
|
|
|
|
Hello,
I need to parse plain Win32 DLL/Exe and need to get all imports and exports from it and to show it on console or GUI(say Win Forms). Is it possible to parse Win32 DLL/Exe in C#.NET, read its export table,import table and get managed types from it. As its unmanaged PE(.NET doesn't allows you to convert unmanaged PE files to managed .NET assemblies, only it generates COM managed assemblies).
So how to parse export and import tables of PE files and take all methods(signatures from it) in managed form.(e.g if char* as argument, it should display as IntPtr)
Regards
Usman
|
|
|
|
|
IMO that is impossible. A native code DLL or EXE file (which uses PE format) normally contains an import and an export table, containing the names of the functions; there is no information about the parameters nor the return type, except maybe, those are to some extent encoded in the C++ name mangling. The mangling is not complete; only some info is available.
Furthermore, a lot of Windows DLLs export functions by number ("ordinal number") rather than by name.
Next, you need to know what the calling convention has to be (CDecl, StdCall, ...). That information is not present, unless you start studying the assembly instructions.
And finally, when using P/Invoka to call a native function from a managed language, one can, and often does, create several prototypes, all mapping to the same function, but taking different parameter types. A typical example would be SendMessage().
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
glitteringsound wrote: I need to parse plain Win32 DLL/Exe and need to get all imports and exports from it and to show it on console or GUI(say Win Forms). Is it possible to parse Win32 DLL/Exe in C#.NET, read its export table,import table and get managed types from it. As its unmanaged PE(.NET doesn't allows you to convert unmanaged PE files to managed .NET assemblies, only it generates COM managed assemblies).
You need to understand, EXACTLY, the Windows PE format. From there, you can write your own library that can parse the file, byte by byte. I've done it myself. No, you can't have the code.
You can start by reading this article[^] and the article it links to. There is also a PDF file that I found that goes into more detail. You can get it from here[^].
Now, you can only get the function names of the import and export tables. There is no information at all inside a PE file that contains anything about the parameters passed or expected by those functions.
|
|
|
|
|
hi, When adding items to a listview, I want the last added item on top instead of bottom. How can I achieve that? Thanks in advance
By the way, when I use sorting property (ascending or descending), everything mess up
modified on Sunday, May 23, 2010 10:18 AM
|
|
|
|
|
Either add the items in reverse order or use Insert(index,item) rather than Add(item) .
CQ de W5ALT
Walt Fair, Jr., P. E.
Comport Computing
Specializing in Technical Engineering Software
|
|
|
|
|
If you are assigning a collection to a listview, you could move the last item of your collection to the first and then assign to the listview. Or else, you could use a temporary collection to build a list in the order you want and then assign to this listview.
My signature "sucks" today
|
|
|
|
|
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace 用户管理
{
public partial class ChangestaffPwd : Form
{
public int flag;
public string str;
public ChangestaffPwd()
{
InitializeComponent();
}
//-----------在DataGridView控件下面textBox控件显示内容-----------
private void show()
{
try
{
this.textBox1.Text = this.dataGridView1.CurrentRow.Cells[0].Value.ToString();
this.textBox2.Text = this.dataGridView1.CurrentRow.Cells[1].Value.ToString();
}
catch (Exception ex)
{
MessageBox.Show("错误描述如下:\r\n" + ex.Message, "不能对列进行排序");
}
}
//---------------DataGridView控件随着选中行的不同,显示不同的内容-------------------
private void alternate()
{
if (this.dataGridView1.Rows.Count != 0)
{
for (int i = 0; i < this.dataGridView1.Rows.Count; )
{
this.dataGridView1.Rows[i].DefaultCellStyle.BackColor = System.Drawing.Color.Orange;
i += 2;
}
}
}
private void ChangestaffPwd_Load(object sender, EventArgs e)
{
SqlConnection con = DBCon.createCon();
SqlDataAdapter sda = new SqlDataAdapter("select StaffID as 用户名,Password as 密码 from Staff ", con);
DataSet ds = new DataSet();
sda.Fill(ds, "table");
this.dataGridView1.DataSource = ds.Tables[0].DefaultView;
show();
}
private void button3_Click(object sender, EventArgs e)
{
if (button3.Text == "添加")
{
this.textBox1.Enabled = true;
if ((str = this.textBox1.Text.ToString()) != "")
{
if (MessageBox.Show("您确定要添加本条记录吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
flag = 1;
MessageBox.Show("请输入用户名和密码并且按确定按钮,才能添加成功!");
return;
}
}
}
}
private void button2_Click(object sender, EventArgs e)
{
if (button2.Text == "修改")
{
if ((str = this.textBox1.Text.ToString()) != "")
{
if (MessageBox.Show("您确定要修改本条记录吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
flag = 2;
MessageBox.Show("请按确定按钮,才能修改成功!");
return;
}
}
}
}
private void button4_Click(object sender, EventArgs e)
{
if (button4.Text == "删除")
{
if ((str = this.textBox1.Text.ToString()) != "")
{
if (MessageBox.Show("您确定要删除本条记录吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
flag = 3;
MessageBox.Show("请按确定按钮,才能删除成功!");
return;
}
}
}
}
private void button5_Click(object sender, EventArgs e)
{
if (button5.Text == "确定")
{
if (flag == 1)
{
SqlConnection con = DBCon.createCon();
con.Open();
//在原表中新建一个新行,然后再数据添加到新行中
SqlCommand cmd = new SqlCommand("insert into Staff values(@StaffID,@Password)", con);
cmd.Parameters.Add("@StaffID", SqlDbType.Char, 10).Value = textBox1.Text;
cmd.Parameters.Add("@Password ", SqlDbType.Char, 20).Value = textBox2.Text;
cmd.Connection = con;
cmd.ExecuteNonQuery();
con.Close();
SqlDataAdapter sda = new SqlDataAdapter("select StaffID as 用户名,Password as 密码 from Staff", con);
DataSet ds = new DataSet();
sda.Fill(ds, "table");
this.dataGridView1.DataSource = ds.Tables[0].DefaultView;
this.textBox1.Enabled = false;
MessageBox.Show("添加记录成功!");
this.textBox1.Enabled = false;
try
{
show();
}
catch (Exception ex)
{
MessageBox.Show("错误描述如下:\r\n" + ex.Message, "没有记录显示!");
}
flag = 0;
}
if (flag == 2 && str != "")
{
SqlConnection con = DBCon.createCon();
con.Open();
SqlCommand cmd = new SqlCommand("update Staff set Password ='" + textBox2.Text.ToString() + "' where UserName='" + str + "'", con);
cmd.Connection = con;
cmd.ExecuteNonQuery();
con.Close();
SqlDataAdapter sda = new SqlDataAdapter("select StaffID as 用户名,Password as 密码 from Staff", con);
DataSet ds = new DataSet();
sda.Fill(ds, "table");
this.dataGridView1.DataSource = ds.Tables[0].DefaultView;
try
{
show();
}
catch (Exception ex)
{
MessageBox.Show("错误描述如下:\r\n" + ex.Message, "没有记录显示!");
}
MessageBox.Show("修改成功!");
flag = 0;
}
if (flag == 3 && str != "")
{
SqlConnection con = DBCon.createCon();
con.Open();
SqlCommand cmd = new SqlCommand("delete from Staff where StaffID='" + str + "'", con);
cmd.Connection = con;
cmd.ExecuteNonQuery();
con.Close();
SqlDataAdapter sda = new SqlDataAdapter("select Staff as 用户名,Password as 密码 from Staff", con);
DataSet ds = new DataSet();
sda.Fill(ds, "table");
this.dataGridView1.DataSource = ds.Tables[0].DefaultView;
try
{
show();
}
catch (Exception ex)
{
MessageBox.Show("错误描述如下:\r\n" + ex.Message, "没有记录显示!");
}
MessageBox.Show("删除成功!");
}
flag = 0;
}
}
private void button10_Click(object sender, EventArgs e)
{
if (button10.Text == "退出")
{
this.Close(); //退出普通用户密码管理维护
}
}
private void dataGridView1_SelectionChanged_1(object sender, EventArgs e)
{
show();
}
private void button1_Click(object sender, EventArgs e)
{
SqlConnection con = DBCon.createCon();
SqlDataAdapter sda = new SqlDataAdapter("select StaffID as 用户名,Password as 密码 from Staff where Username like'" + "%'", con);
DataSet ds = new DataSet();
sda.Fill(ds, "table");
this.dataGridView1.DataSource = ds.Tables[0].DefaultView;
try //有时找不到匹配的记录,有异常
{
show();
}
catch (Exception ex) //对异常进行处理
{
MessageBox.Show("错误描述如下:\r\n" + ex.Message, "没有找到匹配的记录");
return;
}
}
}
}
|
|
|
|
|
It is impossible to read through all that code.
Where (and what) are you getting the error?
My signature "sucks" today
|
|
|
|
|
I did not read that, it is unreadable without proper formatting; please edit and put the code in a big pair of <PRE> tags.
And provide an explanation: what is it you want? what is happening? what are the symptoms? in what line does it fail?
in summary: please read the "how to get an answer" guidelines near the top of this forum.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
modified on Sunday, May 23, 2010 9:45 AM
|
|
|
|
|
In a class there are private fields and several threads all member of the class.
Does it need to lock read access to class fields to avoid reading only of the class members from several threads at the same time.
Чесноков
|
|
|
|
|
Reading is only a problem if there is a possibility that the value of a field may be changed by another thread during the read. If so, then yes you will need to lock it.
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
I've got BackgroundWorker thread in my application which is started in timer event with 10ms interval. It takes about 50ms or larger for a thread to complete. I'm using smaller timer interval to start new thread as soon as possible after previous completed.
I've got IsBusy() method call in timer event to avoid new thread invocation with RunWorkerAsync() if previous is busy by all means.
But in one machine I'm testing it IsBusy fails somehow. Thus before previous thread finished RunWorkerAsync() is called again on the same running Background worker resulting in:
System.InvalidOperationException in Void RunWorkerAsync(System.Object):
Because it is currently too busy, can not perform multiple tasks simultaneously.
How that is possible?
Чесноков
|
|
|
|
|
The IsBusy property is set when you call RunWorkerAsync and isn't unset until immediately before RunWorkerCompleted is raised.
I would start your Timer in your RunWorkerCompleted handler after any other tasks being performed in there so the issue is avoided altogether as there would be no need to check IsBusy at all.
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
There is one thread function and an array of BackgrounWorkers.
There might be N workers running on the same thread function.
On every timer event all array memeber are queried for IsBusy to start new worker.
Timer even reset in RunWorkerCompleted will be hard to handle.
I wonder the reason for IsBusy failure if it is set up immediatly after RunWorkerAsync call?
Or it is set up as the thread enters its function?
Чесноков
|
|
|
|
|
When you call RunWorkerAsync ,
1. The IsBusy flag is checked and if true the exception is thrown.
2. The IsBusy flag is set
It is possible that value of IsBusy could be false when you check it (is at position 1) but by the time you call RunWorkerAsync it could be true (position 2) as there is no internal locking on this property. It wouldn't be too hard to create your own with this locking in place.
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
RunWorkerAsync is a blocking function. Timer tick event can not return until it finished?
Only if the function is non-blocking it would be possible that a second timer event arrives before previous RunWorkerAsync completed.
The same as in blocking non-blocking windows sockets.
Чесноков
|
|
|
|
|
Only if the Timer is a System.Windows.Forms.Timer and if the BackgroundWorker and Timer were started on the same thread.
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
Chesnokov Yuriy wrote: Only if the function is non-blocking it would be possible that a second timer event arrives before previous RunWorkerAsync completed.
Nope. A periodic timer is expected to tick, no matter what. See my other reply to you.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
I said I didn't think it'd be too hard to sync the IsBusy etc. I hate saying that without knowing for sure so I've knocked up a quick version. This should be OK (untested!), but if using other locks or other synchronisation methods in your other code I'd use the MS one. (Needs comments and descriptions adding)
using System;
using System.ComponentModel;
using System.Threading;
namespace DaveyM69.ComponentModel
{
[DefaultEvent("DoWork")]
[DefaultProperty("WorkerReportsProgress")]
public class SaferBackgroundWorker : Component
{
public event DoWorkEventHandler DoWork;
public event ProgressChangedEventHandler ProgressChanged;
public event RunWorkerCompletedEventHandler RunWorkerCompleted;
private bool cancellationPending;
private bool isBusy;
private AsyncOperation operation;
private SendOrPostCallback operationCompleted;
private SendOrPostCallback progressReporter;
private object syncLock = new object();
private bool workerReportsProgress;
private bool workerSupportsCancellation;
private ParameterizedThreadStart workerThreadStart;
public SaferBackgroundWorker()
{
cancellationPending = false;
isBusy = false;
operation = null;
operationCompleted = new SendOrPostCallback(OperationCompleted);
progressReporter = new SendOrPostCallback(ProgressReporter);
workerReportsProgress = false;
workerSupportsCancellation = false;
workerThreadStart = new ParameterizedThreadStart(WorkerThreadStart);
}
[Browsable(false)]
public bool CancellationPending
{
get { lock (syncLock) { return cancellationPending; } }
}
[Browsable(false)]
public bool IsBusy
{
get { lock (syncLock) { return isBusy; } }
}
[DefaultValue(false)]
public bool WorkerReportsProgress
{
get { lock (syncLock) { return workerReportsProgress; } }
set { lock (syncLock) { workerReportsProgress = value; } }
}
[DefaultValue(false)]
public bool WorkerSupportsCancellation
{
get { lock (syncLock) { return workerSupportsCancellation; } }
set { lock (syncLock) { workerSupportsCancellation = value; } }
}
public void CancelAsync()
{
if (!WorkerSupportsCancellation)
throw new InvalidOperationException("Worker doesn't support cancellation");
SetCancellationPending(true);
}
protected virtual void OnDoWork(DoWorkEventArgs e)
{
DoWorkEventHandler eh = DoWork;
if (eh != null)
eh(this, e);
}
protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
{
ProgressChangedEventHandler eh = ProgressChanged;
if (eh != null)
eh(this, e);
}
protected virtual void OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
{
RunWorkerCompletedEventHandler eh = RunWorkerCompleted;
if (eh != null)
eh(this, e);
}
private void OperationCompleted(object state)
{
SetIsBusy(false);
SetCancellationPending(false);
OnRunWorkerCompleted((RunWorkerCompletedEventArgs)state);
}
private void ProgressReporter(object state)
{
OnProgressChanged((ProgressChangedEventArgs)state);
}
public void ReportProgress(int percentProgress)
{
ReportProgress(percentProgress, null);
}
public void ReportProgress(int percentProgress, object userState)
{
if (!WorkerReportsProgress)
throw new InvalidOperationException("Worker doesn't report progress");
ProgressChangedEventArgs arg = new ProgressChangedEventArgs(percentProgress, userState);
if (operation == null)
progressReporter(arg);
else
operation.Post(progressReporter, arg);
}
public void RunWorkerAsync()
{
RunWorkerAsync(null);
}
public void RunWorkerAsync(object argument)
{
if (IsBusy)
throw new InvalidOperationException("Worker is busy");
SetIsBusy(true);
SetCancellationPending(false);
operation = AsyncOperationManager.CreateOperation(null);
workerThreadStart.BeginInvoke(argument, null, null);
}
private void SetCancellationPending(bool value)
{
lock (syncLock) { cancellationPending = value; }
}
private void SetIsBusy(bool value)
{
lock (syncLock) { isBusy = value; }
}
private void WorkerThreadStart(object obj)
{
object result = null;
Exception error = null;
bool cancelled = false;
try
{
DoWorkEventArgs doWorkArgs = new DoWorkEventArgs(obj);
OnDoWork(doWorkArgs);
if (doWorkArgs.Cancel)
cancelled = true;
else
result = doWorkArgs.Result;
}
catch (Exception exception)
{
error = exception;
}
RunWorkerCompletedEventArgs e = new RunWorkerCompletedEventArgs(result, error, cancelled);
operation.PostOperationCompleted(operationCompleted, e);
}
}
}
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
Hi,
I'm not sure what it is you are trying, but it sure sounds like you are having synchronization problems.
Some comments:
1.
As usual, MSDN says: "Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe."
So if you have several threads interested in a single BGW, you'll need some synchronization.
2.
the GUI magic of a BGW (i.e. accessing the GUI safely from within the ProgressChanged or RunWorkerCompleted events) only works if the BGW got created by the main thread.
3.
as (almost) all event handlers, the first parameter in ProgressChanged or RunWorkerCompleted identifies the BGW itself. So it should be rather easy to share a Progress or Completed handler amongst multiple BGWs.
4.
if you want to pass several jobs to the same BGW, to be executed in sequence, why not use a queue (with a lock!), and have DoWork fetch its jobs from that queue?
5.
which timer class are you using? only System.Windows.Forms.Timer ticks on the main thread; the others tend to tick on a ThreadPool thread.
6.
Windows timers have limited resolution; you mentioned 10msec and shorter; not sure you are getting those. Have a read of this: Timer surprises, and how to avoid them[^]
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
There is windows service application that should access some network resource and get data from it (e.g. SQL server, network server with some files, etc...)
There might be N such threads running in parallel each connecting to its own resource. Thus there are N instances of the helper class (performing such remote data collection) in the List array in the instance field of the service.
4. They need to run in parallel not in sequence one after another.
5. Timer is System.Threading.Timer. I'm using logging with milliseconds marks and can confirm accuracy depending on cpu load.
That is the timer tick function:
for (int i = 0; i < this.drives.Count; i++)
{
if (this.drvBackgroundWorkers[i].IsBusy == false)
{
BackgroundWorkerArgument argument = new BackgroundWorkerArgument()
{
threadId = i,
drive = this.drives[i]
};
this.drvBackgroundWorkers[i].RunWorkerAsync(argument);
}
}
drvBackgroundWorkers is not accessed in any thread code only in that tick function.
I wonder the reason for a failure??
Чесноков
|
|
|
|
|
1.
first of all, when a System.Threading.Timer ticks, its handler runs on an arbitrary ThreadPool thread, not on the thread that did start your BGW, and not on the thread that may be executing the current job of your BGW. And the BGW itself needs to access IsBusy() too. So there are several threads involved in accessing the one property.
2.
timer handler executions may overlap, i.e. a second one could start before the first one has finished. Here is proof, run it in debug mode and watch the times, and the counts:
System.Threading.Timer timer;
int count;
public override void Test(int arg) {
timer=new System.Threading.Timer(new TimerCallback(ticker), null, 30, 30);
}
protected void output(string s) {
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff ")+s);
}
public void ticker(object dummy) {
output("ticker("+count+") start");
for (int i=0; i<10000000; i++) { }
output("ticker("+count+") stop");
count++;
if (count>10) {
timer.Change(Timeout.Infinite, Timeout.Infinite);
output("done");
}
}
[ADDED]
I only tested on a dual-core, however I don't think it needs a multi-core for overlaps to occur.
[/ADDED]
One way to fix it, would be to make the timer single-shot; and fire it again (using Change) when its handler is done.
3.
you are trying to feed new jobs to existing BGW. The easy way out would be to create a new BGW each time; yes, that is more expensive.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
modified on Sunday, May 23, 2010 11:18 AM
|
|
|
|
|
Hi all,
I have a DataGridView where the user can change the columns widths (by dragging the column header divider). However, I'd like to disable the functionality that double-clicking the column header divider auto-resizes the column with. I tried using the ColumnDividerDoubleClick event to handle this event manually, but the column width still automatically resizes.
Ideas?
Thanks!
Eyal.
|
|
|
|
|