I cannot find the solution for this problem, here is the simplified example:
On a windows form I have 2 text boxes (invokeText1, invokeText2) and two buttons (invokeButton1, invokeButton2).
There are both button clicks:
private void invokeButton1_Click(object sender, EventArgs e)
{
Form1.GetVersionCompleted += (object sender1, AsyncCompletedEventArgs e1) =>
{
this.Invoke((MethodInvoker)(() =>
{
invokeText1.Text = DateTime.Now.ToString();
}));
};
Form1.GetVersionAsync();
}
private void invokeButton2_Click(object sender, EventArgs e)
{
Form1.GetVersionCompleted += (object sender1, AsyncCompletedEventArgs e1) =>
{
this.Invoke((MethodInvoker)(() =>
{
invokeText2.Text = DateTime.Now.ToString();
}));
};
Form1.GetVersionAsync();
}
Both call to the async method:
public static event EventHandler<AsyncCompletedEventArgs> GetVersionCompleted;
public static void GetVersionAsync()
{
ThreadPool.QueueUserWorkItem(o =>
{
try
{
string result = DateTime.Now.ToString();
GetVersionCompleted(
null,
new AsyncCompletedEventArgs(
null,
false,
result));
}
catch (Exception ex)
{
GetVersionCompleted(
null,
new AsyncCompletedEventArgs(
ex,
false,
null));
}
});
}
When a single button clicked, it updates its related text box only.
When both buttons clicked, each updates both text boxes.
I think there should be something simple, but I cannot find what :(
Oh, the problem is solved! It happens because I am subscribing to the same event several times:
Form1.GetVersionCompleted +=
The right implementation would be something like:
public delegate void OnCompleted<T>(T result, Exception ex);
public static void GetVersionAsync(OnCompleted<string> completed)
{
ThreadPool.QueueUserWorkItem(o =>
{
try
{
string result = DateTime.Now.ToString();
if (completed != null)
{
completed(result, null);
}
}
catch (Exception ex)
{
if (completed != null)
{
completed(null, ex);
}
}
});
}
private void invokeButton1_Click(object sender, EventArgs e)
{
Form1.GetVersionAsync((string result, Exception ex) =>
{
this.Invoke((MethodInvoker)(() =>
{
invokeText1.Text = DateTime.Now.ToString();
}));
});
}
private void invokeButton2_Click(object sender, EventArgs e)
{
Form1.GetVersionAsync((string result, Exception ex) =>
{
this.Invoke((MethodInvoker)(() =>
{
invokeText2.Text = DateTime.Now.ToString();
}));
});
}
Related
hello i am trying to autoconnect to bluetooth and return back to main activity,but i am not able to auto connect and return back from current activity to main activty....
Of course if there are more easy ways to do it I would appreciate it very much.
here is code==>
public class SimpleUiActivity extends Activity {
private static final String TAG = SimpleUiActivity.class.getSimpleName();
private static final int RESULT_OK = 1;
private static final int RQS_IMAGE = 2;
private static final int RQS_I = 3;
private BluetoothAdapter BA;
private Map<String, Gpio> mGpioMap = new LinkedHashMap<>();
Button ble;
Button campre;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
LinearLayout gpioPinsView = (LinearLayout) findViewById(R.id.gpio_pins);
LayoutInflater inflater = getLayoutInflater();
PeripheralManagerService pioService = new PeripheralManagerService();
for (String name : pioService.getGpioList()) {
View child = inflater.inflate(R.layout.list_item_gpio, gpioPinsView, false);
Switch button = (Switch) child.findViewById(R.id.gpio_switch);
button.setText(name);
gpioPinsView.addView(button);
Log.d(TAG, "Added button for GPIO: " + name);
try {
final Gpio ledPin = pioService.openGpio(name);
ledPin.setEdgeTriggerType(Gpio.EDGE_NONE);
ledPin.setActiveType(Gpio.ACTIVE_HIGH);
ledPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
button.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
try {
ledPin.setValue(isChecked);
} catch (IOException e) {
Log.e(TAG, "error toggling gpio:", e);
buttonView.setOnCheckedChangeListener(null);
// reset button to previous state.
buttonView.setChecked(!isChecked);
buttonView.setOnCheckedChangeListener(this);
}
}
});
mGpioMap.put(name, ledPin);
} catch (IOException e) {
Log.e(TAG, "Error initializing GPIO: " + name, e);
// disable button
button.setEnabled(false);
}
//-----------------
ble=(Button)findViewById(R.id.autobluetooth);
ble.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
ble.postDelayed(new Runnable() {
#Override
public void run() {
BA = BluetoothAdapter.getDefaultAdapter();
BA.enable();
Intent intent=new Intent(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
Log.i("aaa","i am here");
// startActivityForResult(intent, RQS_IMAGE);// Activity is started with requestCode 2
finish();
}
}, 10000);
}
});
//-----------------
//-----------------
campre=(Button)findViewById(R.id.camerapreview);
campre.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent1=new Intent(SimpleUiActivity.this,MainActivity.class);
startActivityForResult(intent1, RQS_I);// Activity is started with requestCode 3
}
});
//----------------
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
// check if the request code is same as what is passed here it is 2
if(requestCode==RESULT_OK) {
switch (requestCode) {
case RQS_IMAGE:
Log.i("abc", "i am here");
Toast.makeText(getApplicationContext(), "Bluetooth switched ON", Toast.LENGTH_LONG).show();
finish();
// textsource.setText(source.toString());
break;
case RQS_I:
break;
}
}
}
#Override
protected void onDestroy() {
super.onDestroy();
for (Map.Entry<String, Gpio> entry : mGpioMap.entrySet()) {
try {
entry.getValue().close();
} catch (IOException e) {
Log.e(TAG, "Error closing GPIO " + entry.getKey(), e);
}
}
mGpioMap.clear();
}
}
There seems to be no way of disconnecting a socket without causing a connection reset error on the server side.
I'm using the com.codename1.io.Socket and com.codename1.io.SocketConnection implementations within a tester app. My code is as follows:
private SpanLabel lblStatus;
private SpanLabel lblIncoming;
private CustomSocketConnection con;
private Thread tIncoming;
public ConnectForm() {
con = getSocketConnection();
Button btnConnect = getConnectButton();
Button btnDisconnect = getDisconnectButton();
Button btnSendMessage = getSendMessageButton();
lblStatus = getInfoLabel();
lblIncoming = getIncomingLabel();
setLayout(new BoxLayout(BoxLayout.Y_AXIS));
addComponent(btnConnect);
addComponent(btnDisconnect);
addComponent(btnSendMessage);
addComponent(lblStatus);
addComponent(lblIncoming);
}
private Button getConnectButton() {
Button btn = new Button("Connect (localhost)");
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Socket.connect("localhost", 8687, con);
}
});
return btn;
}
private Button getDisconnectButton() {
Button btn = new Button("Disconnect");
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//??? I don't know how to do this
try {
tIncoming.join();
} catch (Exception e) {
e.printStackTrace();
tIncoming.interrupt();
}
}
});
return btn;
}
private Button getSendMessageButton() {
Button btn = new Button("Send Message");
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
try {
con.os.write("Hello".getBytes());
con.os.write(Integer.parseInt("04", 16)); //end of transmit
con.os.flush();
lblStatus.setText("Message Sent");
} catch (Exception e) {
e.printStackTrace();
}
}
});
return btn;
}
private SpanLabel getInfoLabel() {
return new SpanLabel("Disconnected");
}
private SpanLabel getIncomingLabel() {
return new SpanLabel("...");
}
private CustomSocketConnection getSocketConnection() {
return new CustomSocketConnection();
}
class CustomSocketConnection extends SocketConnection {
public OutputStream os;
public InputStream is;
#Override
public void connectionError(int errorCode, String message) {
lblStatus.setText("Error Connecting. ErrorCode: " + errorCode + " Message: " + message);
}
#Override
public void connectionEstablished(InputStream is, OutputStream os) {
lblStatus.setText("Connected :)");
this.is = is;
this.os = os;
spawnIncomingMessageWatcher();
}
}
private void spawnIncomingMessageWatcher() {
tIncoming = new Thread(new Runnable() {
public void run() {
String s = "";
int eot = Integer.parseInt("04", 16);
while (con.isConnected()) {
try {
int temp;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (((temp = con.is.read()) != -1) && (temp != eot)) {
baos.write(temp);
}
lblIncoming.setText(new String(baos.toByteArray()));
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
tIncoming.start();
}
With the getDisconnectButton() method, I do not know how to properly disconnect from the server, as the SocketConnection object does not seem to have an appropriate method for this.
If you call close() on either the Input- or OutputStream then you close the Socket, code from Socket.SocketInputStream class link.
public void close() throws IOException {
closed = true;
if(Util.getImplementation().isSocketConnected(impl)) {
Util.getImplementation().disconnectSocket(impl);
con.setConnected(false);
}
}
So first send close instruction to Server and then close a stream.
Hope this helps,
I want to display some data on form load in a data gridview , the data which i want to display is in large number of rows , when i use background worker processor it show me the following error.
My code:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
FTPUtility obj = new FTPUtility();
dataGridViewRequest.DataSource = obj.ListRequestFiles();
dataGridViewRequest.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewRequest.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewRequest.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.DataSource = obj.ListResponseFiles();
dataGridViewResponses.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Form load:
private void FormFTP_Load(object sender, EventArgs e)
{
try
{
//this.comboBoxRequests.SelectedIndex = 0;
backgroundWorker1.RunWorkerAsync();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
There are many different ways to prevent the form from being freezed.
For example you can load your data like this:
private async void Form_Load(object sender, EventArgs e)
{
//do some initializations
await LoadData();
//do some other initializations that you need to perform.
}
private async Task LoadData()
{
//Load your data here
//For example
FTPUtility obj = new FTPUtility();
dataGridViewRequest.DataSource = obj.ListRequestFiles();
}
This way when running the form, the commands run in the sequence you wrote while the UI is responsive and you will not face with common difficulties of using BackgroundWorker or threads like Cross thread operation exceptions.
The key point is in using async/await. For more information read Asynchronous Programming with Async and Await
Remember that this way, every where you want to call LoadData, you should call it this way:
await LoadData();
And the method that you write this code in, should be async:
private async void RefreshButton_Click(object sender, EventArgs e)
{
await LoadData();
}
EDIT For .Net 4.0
For .Net 4.0 you can use both Task.Run or BackgroundWorker. I recommend Task.Run because it is more simple and more readable.
Please note Cross Thread Operation Exception will throw when you access the UI elements from another thread than UI. In this situations you should use this.Invoke(new Action(()=>{/*Access UI Here*/})); instead. And never put a time-consuming task in your invoke part.
BackgroundWorker Approach:
private void Form1_Load(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
//If you put some code here for example MessageBox.Show("");
//The code will immadiately run and don't wait for worker to complete the task.
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
this.LoadData();
}
public void LoadData()
{
var ftp = new FtpUtility();
var data = ftp.ListRequestFiles();
this.Invoke(new Action(() =>
{
//Setup columns and other UI stuff
//Set datasource of grid
this.dataGridView1.DataSource = data;
}));
}
Remember everywhere you formerly used LoadData, now you should use backgroundWorker1.RunWorkerAsync(); instead.
If you want to do a job after the worker completes the task, put your job in backgroundWorker1_RunWorkerCompleted or in Invoke part of LoadData.
Task.Run Approach
private void Form1_Load(object sender, EventArgs e)
{
Task.Run(() =>
{
LoadData();
})
.ContinueWith(x =>
{
//You can put codes you want run after LoadData completed here
//If you access the UI here, you should use Invoke
});
//If you put some code here for example MessageBox.Show("");
//The code will immadiately run and don't wait for worker to complete the task.
}
public void LoadData()
{
var ftp = new FtpUtility();
var data = ftp.ListRequestFiles();
this.Invoke(new Action(() =>
{
//Setup columns and other UI stuff
//Set datasource of grid
this.dataGridView1.DataSource = data;
}));
}
Remember everywhere you formerly used LoadData, now you should use Task.Run(()=>{LoadData();}); instead.
If you want to do a job after the LoadData completes, put your job in ContinueWith or in Invoke part of LoadData.
Try this.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
dataGridViewRequest.Invoke(new Action(() => {
FTPUtility obj = new FTPUtility();
dataGridViewRequest.DataSource = obj.ListRequestFiles();
dataGridViewRequest.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewRequest.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewRequest.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.DataSource = obj.ListResponseFiles();
dataGridViewResponses.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void FormFTP_Load(object sender, EventArgs e)
{
try
{
//this.comboBoxRequests.SelectedIndex = 0;
backgroundWorker1.RunWorkerAsync();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
My Android Media Player randomly stops playing. I dont know why. I am using two Media Players for a gapless loop. After a while the sound stops. The issue appers after seconds or minutes. I tried several fixes:
declaring static media player (according to this)
reducing bitrate (now i have 64 bit/s ogg files)
setWakeMode() (according to this)
None of them solved my problem. Any suggestions? THX!
Code:
private Context context;
private Handler handler;
private Runnable myRunnable;
/*Ausgabe*/
private ImageView cover;
private static MediaPlayer mp;
private static MediaPlayer mp2;
private Uri myUri;
private String curTitle;
private String curPow;
private boolean curMP; //false=mp1, true= mp2
/*Control*/
private ToggleButton onoff;
private Spinner spinner;
private Switch throttle;
/*Volume*/
private SeekBar volumeSeekbar = null;
private AudioManager audioManager = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jukebox);
context = this;
/*Control-Setup*/
initControls();
initButtons();
/*Sound Setup*/
mp = new MediaPlayer();
mp2 = new MediaPlayer(); //workarround f gapless looping
setDisc("classic");
/*Image Setup*/
cover = (ImageView) findViewById(R.id.imageGallerie);
cover.setImageResource(R.drawable.classic);
}
#Override
protected void onDestroy() {
super.onDestroy();
if(mp!=null){
mp.stop();
mp.release();
mp = null;
}
if(mp2!=null){
mp2.stop();
mp2.release();
mp2=null;
}
}
/*sound-file selection*/
public void setDisc(String s){
String tmp = "";
if(throttle.isEnabled()==true && throttle.isChecked())
tmp="2";
myUri = getUri(s+tmp);
curTitle=s;
curPow=tmp;
try {
mp.reset();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.setDataSource(context, myUri);
mp.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mp.prepare();
mp2.reset();
mp2.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp2.setDataSource(context, myUri);
mp2.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mp2.prepare();
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp2.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
setMyLoop();
play();
}
});
}
});
} catch (IllegalArgumentException e) {
e.printStackTrace();
// Arrr, devensive programming... change request
Toast.makeText(context, getResources().getString(R.string.error3), Toast.LENGTH_LONG).show();
} catch (SecurityException e) {
e.printStackTrace();
Toast.makeText(context, getResources().getString(R.string.error3), Toast.LENGTH_LONG).show();
} catch (IllegalStateException e) {
e.printStackTrace();
Toast.makeText(context, getResources().getString(R.string.error3), Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(context, getResources().getString(R.string.error3), Toast.LENGTH_LONG).show();
}
}
/*Gapless Looping - api 16 oder higher */
public void setMyLoop(){
final AssetFileDescriptor afd = getResources().openRawResourceFd(getRawId(this, curTitle.concat(curPow)));
mp.setNextMediaPlayer(mp2);
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mediaPlayer.prepare();
} catch (Exception e) {
Toast.makeText(context, getResources().getString(R.string.error1), Toast.LENGTH_LONG).show();
}
mp2.setNextMediaPlayer(mp);
}
});
mp2.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mediaPlayer.prepare();
} catch (Exception e) {
Toast.makeText(context, getResources().getString(R.string.error2), Toast.LENGTH_LONG).show();
}
mp.setNextMediaPlayer(mp2);
}
});
}
/*play sound*/
public void play(){
if(onoff.isChecked()){
mp.start();
}
}
/*gui control*/
#Override
public void onClick(View v) {
if(v == onoff){
if(onoff.isChecked()==false){
mpAnhalten();
}
else{
mpStarten();
}
}
...
}
#Override
public void onPause(){
super.onPause();
if(mp!=null)
mpAnhalten();
}
/*pause player*/
public void mpAnhalten(){
if(mp2.isPlaying()){
mp2.pause();
curMP=true;
}
else {
if(mp.isPlaying()){
mp.pause();
}
curMP=false;
}
}
/*start player again*/
public void mpStarten(){
if(curMP==true)
mp2.start();
else
mp.start();
}
#Override
public void onResume(){
super.onResume();
View v = findViewById(R.id.LinearLayout1);
if(mp!=null && onoff.isChecked())
mpStarten();
}
/*volume*/
private void initControls(){
try{
volumeSeekbar = (SeekBar)findViewById(R.id.seekBar1);
getApplicationContext();
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
volumeSeekbar.setMax(audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
volumeSeekbar.setProgress(audioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
volumeSeekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar arg0) {
}
#Override
public void onStartTrackingTouch(SeekBar arg0) {
}
#Override
public void onProgressChanged(SeekBar arg0, int progress, boolean arg2) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
progress, 0);
}
});
}
catch (Exception e)
{
Toast.makeText(getApplicationContext(), getResources().getString(R.string.error1), Toast.LENGTH_LONG).show();
}
}
/*gui-control sound-file selection*/
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selection = parent.getItemAtPosition(position).toString();
if(selection.equals("Classic")){
cover.setImageResource(getImageId(this, "classic"));
cover.invalidate();
throttle.setEnabled(true);
setDisc("classic");
}
...
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
// TODO Auto-generated method stub
}
...
/*oncreate submethode*/
private void initButtons(){
/*On Off*/
onoff = (ToggleButton) findViewById(R.id.onoff);
onoff.setChecked(false);
onoff.setOnClickListener(this);
/*track selection*/
spinner = (Spinner) findViewById(R.id.spinner1);
spinner.setOnItemSelectedListener(this);
List<String> list = new ArrayList<String>();
list.add("Modern");
...
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, list);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(dataAdapter);
/*power*/
throttle = (Switch) findViewById(R.id.throttle);
throttle.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
setDisc(curTitle);
}
});
throttle.setChecked(false);
}
Edit:
This is the log output:
07-26 16:07:58.707: W/SoftVorbis(191): vorbis_dsp_synthesis returned -135
07-26 16:07:58.779: E/NuPlayerDecoder(191): Stream error for OMX.google.vorbis.decoder (err=-1007), EOS successfully queued
07-26 16:07:58.780: E/NuPlayer(191): received error(0xfffffc11) from audio decoder, flushing(0), now shutting down
07-26 16:07:58.780: E/MediaPlayer(30858): error (1, -1007)
07-26 16:07:58.781: E/MediaPlayer(30858): Error (1,-1007)
I don't know what is wrong.
private void btnSend_Click(object sender, RoutedEventArgs e)
{
Button obj=(Button)sender;
obj.Content="Cancel";
SendImage send = new SendImage();
Thread t = new Thread(send.Image);
t.Start();
//run separate thread.(very long, 9 hours)
//so dont wait.
//but the button should be reset to obj.Content="Send"
//Can I do this?
}
I want the button to be reset to "Send" (after completion of thread). But form should not wait. Is this possible?
You can do this more elegantly using the BackgroundWorker class.
XAML for the Button:
<Button x:Name="btnGo" Content="Send" Click="btnGo_Click"></Button>
Code :
private BackgroundWorker _worker;
public MainWindow()
{
InitializeComponent();
_worker = new BackgroundWorker();
_worker.WorkerSupportsCancellation = true;
_worker.WorkerReportsProgress = true;
}
private void btnGo_Click(object sender, RoutedEventArgs e)
{
_worker.RunWorkerCompleted += delegate(object completedSender, RunWorkerCompletedEventArgs completedArgs)
{
Dispatcher.BeginInvoke((Action)(() =>
{
btnGo.Content = "Send";
}));
};
_worker.DoWork += delegate(object s, DoWorkEventArgs args)
{
Dispatcher.BeginInvoke((Action)(() =>
{
btnGo.Content = "Cancel";
}));
SendImage sendImage = args.Argument as SendImage;
if (sendImage == null) return;
var count = 0;
while (!_worker.CancellationPending)
{
Dispatcher.BeginInvoke((Action)(() =>
{
btnGo.Content = string.Format("Cancel {0} {1}", sendImage.Name, count);
}));
Thread.Sleep(100);
count++;
}
};
if (_worker.IsBusy)
{
_worker.CancelAsync();
}
else
{
_worker.RunWorkerAsync(new SendImage() { Name = "Test" });
}
}
Make the Button a member of your Window/UserControl class (by giving it a Name in XAML). When the thread eventually finishes, do this before returning from the thread method:
myButton.Dispatcher.BeginInvoke(
(Action)(() => myButton.Content = "Send"));