I'm having a problem with my logger class.
Here's the code:
#include "Logger.h"
Logger::Logger()
{
fileName = new string("log.txt");
out = new ofstream(*fileName, ofstream::out);
stream = new vector<string>;
changed = new bool;
condition = new condition_variable;
myMutex = new mutex;
running = new bool;
if (running)
{
PostQuitMessage(500);
}
if (!out->is_open())
{
exit(3);
}
*running = false;
T = new thread(&Logger::myrun, this);
}
Logger::~Logger()
{
delete fileName;
delete out;
delete stream;
delete changed;
delete condition;
delete myMutex;
delete running;
delete T;
}
void Logger::myrun()
{
*running = true;
while (*running)
{
unique_lock<mutex> lock(*myMutex);
condition->wait(lock, [this] { return *changed; });
for (int c = 0; c < stream->size(); c++)
{
*out << stream->at(c) << endl;
}
stream->clear();
*changed = false;
}
Sleep(100);
}
void Logger::log(string msg)
{
unique_lock<mutex> lock(*myMutex);
stream->push_back(msg);
*changed = true;
condition->notify_one();
}
void Logger::stop()
{
*running = false;
*changed = true;
condition->notify_one();
T->join();
out->close();
}
The thread hangs after the line T->join();
My question is - why does it hang? And how should I resolve it? Please show me in code :)
Thanks in advance!
P.S. All variables are pointers because I use this code is in a dllexport, VS gives me a lot of warnings that it "needs to have dll-interface to be used by clients of class 'Logger'". If anyone has some tips on this one - You are welcome to post :D
I fixed the issue by puttin the destructor code into the method stop and closing the file after joining the thread. I think
Related
I'm trying to load information with worker and using reportprogress to update progress bar until finshing, but the worker stop working and doesn't finish the for loop or continue after several minutes. I don't know what's the problem and I tried every post here I can find related to this problem and didn't get anything. I hope I can finally get an answer posting my problem here.
Here's the relevant code:
public class Class1
{
public BackgroundWorker unit_read_data_setting_Worker;
public Class1()
{
unit_read_data_setting_Worker = new BackgroundWorker();
unit_read_data_setting_Worker.WorkerReportsProgress = true;
unit_read_data_setting_Worker.WorkerSupportsCancellation = false;
unit_read_data_setting_Worker.DoWork += new DoWorkEventHandler(unit_read_data_setting);
unit_read_data_setting_Worker.ProgressChanged += new ProgressChangedEventHandler(_update_progress);
unit_read_data_setting_Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Completed);
}
public void unit_read_data_setting(object sender = null, DoWorkEventArgs e = null)
{
lock (FamilyTreeViewModel.Lock_ParameterList)
{
ObservableCollection<Parameter_UC_ViewModel> _internal_parameter_list =
FamilyTreeViewModel.GetInstance.ParameterList;
if (FamilyTreeViewModel.GetInstance.SelectedUnitSetting != null)
{
if (_internal_parameter_list.Count > 0)
{
for (int i = 0; i < _internal_parameter_list.Count; i++)
{
int startValue = i * 100 / _internal_parameter_list.Count;
unit_read_data_setting_Worker.ReportProgress(startValue);
// do stuff related to the index
// when progress_bar at 76 value, the loop stoppes and cotinue after a minute
}
}
}
}
}
private void _update_progress(object sender, ProgressChangedEventArgs e)
{
FamilyTreeViewModel.GetInstance.Unit_read_data_setting_progress_bar = e.ProgressPercentage;
}
private void Completed(object sender, RunWorkerCompletedEventArgs e)
{
// never gets here but there's no error
}
}
Well, I would like to implement a function, such when the application starts, the recorder will start to recording, and when the user keeps silence there is nothing going to happen until the user speaks. Then, it will save the PCM file of user's voice and then stop recording.
Voice Detection in Android Application
Above is the question I have found similar as mine, but the answer of this link can not work. And I don't know how to modify it, since I don't understand the concept of the code.
Please help me~
Well, I solved my problem, here is my solution.
I modified the code came from this url:
Voice Detection in Android Application
private static final String TAG = "MainActivity";
private static int RECORDER_SAMPLERATE = 44100;
private static int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_STEREO;
private static int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private Button btn, btn_convert, btn_play;
private TextView txv;
boolean isRecording = false;
private File file;
private AudioRecord audioRecord;
int bufferSizeInBytes = 0;
Context context = MainActivity.this;
// path
final String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/final.pcm" ;
final String outpath = path.replace(".pcm", ".wav");
public void autoRecording(){
// Get the minimum buffer size required for the successful creation of an AudioRecord object.
bufferSizeInBytes = AudioRecord.getMinBufferSize( RECORDER_SAMPLERATE,
RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING
);
// Initialize Audio Recorder.
AudioRecord audioRecorder = new AudioRecord( MediaRecorder.AudioSource.MIC,
RECORDER_SAMPLERATE,
RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING,
bufferSizeInBytes
);
// Start Recording.
txv.setText("Ing");
audioRecorder.startRecording();
isRecording = true;
// for auto stop
int numberOfReadBytes = 0;
byte audioBuffer[] = new byte[bufferSizeInBytes];
boolean recording = false;
float tempFloatBuffer[] = new float[3];
int tempIndex = 0;
// create file
file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/final.pcm");
Log.d(TAG, "recording: file path:" + file.toString());
if (file.exists()){
Log.d(TAG,"file exist, delete file");
file.delete();
}
try {
Log.d(TAG,"file created");
file.createNewFile();
} catch (IOException e) {
Log.d(TAG,"didn't create the file:" + e.getMessage());
throw new IllegalStateException("did not create file:" + file.toString());
}
// initiate media scan and put the new things into the path array to
// make the scanner aware of the location and the files you want to see
MediaScannerConnection.scanFile(context, new String[] {file.toString()}, null, null);
// output stream
OutputStream os = null;
DataOutputStream dos = null;
try {
os = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(os);
dos = new DataOutputStream(bos);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// While data come from microphone.
while( true )
{
float totalAbsValue = 0.0f;
short sample = 0;
numberOfReadBytes = audioRecorder.read( audioBuffer, 0, bufferSizeInBytes );
// Analyze Sound.
for( int i=0; i<bufferSizeInBytes; i+=2 )
{
sample = (short)( (audioBuffer[i]) | audioBuffer[i + 1] << 8 );
totalAbsValue += (float)Math.abs( sample ) / ((float)numberOfReadBytes/(float)2);
}
// read in file
for (int i = 0; i < numberOfReadBytes; i++) {
try {
dos.writeByte(audioBuffer[i]);
} catch (IOException e) {
e.printStackTrace();
}
}
// Analyze temp buffer.
tempFloatBuffer[tempIndex%3] = totalAbsValue;
float temp = 0.0f;
for( int i=0; i<3; ++i )
temp += tempFloatBuffer[i];
if( (temp >=0 && temp <= 2100) && recording == false ) // the best number for close to device: 3000
{ // the best number for a little bit distance : 2100
Log.i("TAG", "1");
tempIndex++;
continue;
}
if( temp > 2100 && recording == false )
{
Log.i("TAG", "2");
recording = true;
}
if( (temp >= 0 && temp <= 2100) && recording == true )
{
Log.i("TAG", "final run");
//isRecording = false;
txv.setText("Stop Record.");
//*/
tempIndex++;
audioRecorder.stop();
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
The function of this function:
if you call this function, the recorder will start recording, and once you make sound(Notify if there are some noise it will stop too.) it will stop recording and save into file(pcm format).
How to fix this code using multithreading?
It's working but I need to know how to add a thread to this code, I think that this is why the progress bar not updating progressively!
public void copyfile(ActionEvent event){
try {
File fileIn = new File(filepath);
long length = fileIn.length();
long counter = 0;
double r;
double res=(counter/length);
filename=fieldname.getText();
FileInputStream from=new FileInputStream(filepath);
FileOutputStream to=new FileOutputStream("C:\\xampp\\htdocs\\videos\\"+filename+".mp4");
byte [] buffer = new byte[4096];
int bytesRead=0;
while( (r=bytesRead=from.read(buffer))!= 1){
progressbar.setProgress(counter/length);
counter += r*100;
to.write(buffer, 0, bytesRead);
System.out.println("File is loading!!"+(counter/length));
}
from.close();
to.close();
} catch (Exception e) {
progress.setText("upload is finished!!");
}
}
Can you please post any solution, which helps me?
Thanks for all advices.
There is an example of associating a progress bar with progress of a concurrent task in Oracle's JavaFX 8 concurrency documentation.
import javafx.concurrent.Task;
Task task = new Task<Void>() {
#Override public Void call() {
static final int max = 1000000;
for (int i=1; i<=max; i++) {
if (isCancelled()) {
break;
}
updateProgress(i, max);
}
return null;
}
};
ProgressBar bar = new ProgressBar();
bar.progressProperty().bind(task.progressProperty());
new Thread(task).start();
I'm trying to handle thread pool in a class.
below is my code.
#include <Windows.h>
class ClassA
{
public : // user API
ClassA()
{
}
~ClassA()
{
}
public : //my muiti-thread func
void init()
{
//*************************************
// multithread Initialization
//*************************************
pool = NULL;
cleanupgroup = NULL;
rollback = 0;
bool bRet = false;
pool = CreateThreadpool(NULL);
if(NULL == pool)
{
goto cleanPool;
}
rollback = 1;
SetThreadpoolThreadMaximum(pool, 5);
bRet = SetThreadpoolThreadMinimum(pool, 10);
if (FALSE == bRet) {
goto cleanPool;
}
cleanupgroup = CreateThreadpoolCleanupGroup();
if (NULL == cleanupgroup) {
goto cleanPool;
}
rollback = 2;
SetThreadpoolCallbackPool(&CallBackEnviron, pool);
SetThreadpoolCallbackCleanupGroup(&CallBackEnviron,
cleanupgroup,
NULL);
return ;
cleanPool:
switch (rollback)
{
case 2:
// Clean up the cleanup group.
CloseThreadpoolCleanupGroup(cleanupgroup);
case 1:
// Clean up the pool.
CloseThreadpool(pool);
default:
break;
}
return ;
}
void foo()
{
PTP_WORK work = NULL;
work = CreateThreadpoolWork(ClassA::_delegate,
NULL,
&CallBackEnviron);
}
static void __stdcall _delegate(PTP_CALLBACK_INSTANCE Instance, PVOID Parameter, PTP_WORK Work)
{
//some code
}
PTP_POOL pool;
UINT rollback;
TP_CALLBACK_ENVIRON CallBackEnviron;
PTP_CLEANUP_GROUP cleanupgroup;
};
int main()
{
ClassA a;
a.init();
a.foo();
}
If you make a project and execute this code, it gets unhandled execption...
I have no clue why...
I think the exception is caused by an uninitialized structure CallBackEnviron. The documentation states that this structure must be initialized by InitializeThreadpoolEnvironment
This following code gives me the error below . I think I need "InvokeRequired" . But I don't understand how can I use?
error:Cross-thread operation not valid: Control 'statusBar1' accessed from a thread other than the thread it was created on.
the code :
public void CalculateGeneration(int nPopulation, int nGeneration)
{
int _previousFitness = 0;
Population TestPopulation = new Population();
for (int i = 0; i < nGeneration; i++)
{
if (_threadFlag)
break;
TestPopulation.NextGeneration();
Genome g = TestPopulation.GetHighestScoreGenome();
if (i % 100 == 0)
{
Console.WriteLine("Generation #{0}", i);
if ( ToPercent(g.CurrentFitness) != _previousFitness)
{
Console.WriteLine(g.ToString());
_gene = g;
statusBar1.Text = String.Format("Current Fitness = {0}", g.CurrentFitness.ToString("0.00"));
this.Text = String.Format("Sudoko Grid - Generation {0}", i);
Invalidate();
_previousFitness = ToPercent(g.CurrentFitness);
}
if (g.CurrentFitness > .9999)
{
Console.WriteLine("Final Solution at Generation {0}", i);
statusBar1.Text = "Finished";
Console.WriteLine(g.ToString());
break;
}
}
}
}
Easiest for reusability is to add a helper function like:
void setstatus(string txt)
{
Action set = () => statusBar1.Text = txt;
statusBar1.Invoke(set);
}
Or with the invokerequired check first:
delegate void settextdelegate(string txt);
void setstatus(string txt)
{
if (statusBar1.InvokeRequired)
statusBar1.Invoke(new settextdelegate(setstatus), txt);
else
statusBar1.Text = txt;
}
Either way the status can then be set like
setstatus("Finished");
For completeness I should add that even better would be to keep your calculating logic separated from your form and raise a status from within your calculating functionality that can be hanled by the form, but that could be completely out of scope here.