Transition between child thread to Application thread in JavaFX - multithreading

I am new to JavaFX. I am trying to implement multithreading in my project.
Here I want to do download work in a background thread. But in the code, some components like Filechooser and label are not accessed by the background thread, so I used Platform.runLater for it. But then I am stuck in between. Please guide me.
FileChooser fc = new FileChooser();
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("Compressed(zipped) Folder (*.zip)", "*.zip");//Compressed(zipped) Folder (*.gz)", "*.gz"
fc.getExtensionFilters().add(extFilter);
String downloadsLocation = System.getProperty("user.home") + "/Downloads/";
/// get a File file with name as you save in file chooser
Platform.runLater(()->{
System.out.println("Inside runlator"+Thread.currentThread());
file = fc.showSaveDialog(downloadMultiTraceFileButton.getScene().getWindow());
System.out.println("Path of file->" + file.getAbsolutePath());
file.mkdirs();
});
System.out.println("after runlator"+Thread.currentThread());
Thread.sleep(1000);
System.out.println("after sleep"+Thread.currentThread());
File theDir = null;
try{
theDir = new File(destFile.getAbsolutePath());
}catch(Exception e){
System.out.println(e);
}
/// Iterating through the slected item of trace files one by one for create a file and then fill it
for (String str : traceFileListView.getSelectionModel().getSelectedItems()) {
System.out.println("inside of the for loop "+Thread.currentThread());
File myFile = new File(theDir.getAbsolutePath() + "\\" + str);
/// make new file if myFile doesnt exist
if (!myFile.exists()) {
myFile.createNewFile();
}
Here backgroung thread is going through it. But this thread is not going to this part of code.
File theDir = null;
try{
theDir = new File(destFile.getAbsolutePath());
}catch(Exception e){
System.out.println(e);
}
Please give me solution. I tried every possibility like inserting Thread.currentthread.sleep(1000) and some other things too.

Related

I have my own code to create a excel file and I want to send that as an attachment to email without saving file in local system

I am working on a case where I will be supplied with data and I will create a excel file using that data.
Right now I am creating it in my local system and later adding that as an attachment and sending through email using Java Mail Service.
But I dont want to store excel file in my local system and I want to just pass the stream object to email service and send email. So that there wont be any local storage of file still able to send attachment.
Please reply if there is any solution ?
// Created WorkBook
HSSFWorkbook workbook = new HSSFWorkbook();
FileOutputStream outputStream = new FileOutputStream(FILE_NAME)) workbook.write(outputStream);
here FILE_NAME is fully qualified system path where I will be storing file.
I want to skip this and directly send attachment
I'm using an approach like this and it is working fine:
File file = File.createTempFile("Report", "xlsx");
file.deleteOnExit();
Path path = file.toPath();
try (final FileOutputStream fileOut = new FileOutputStream(file)) {
try (final XSSFWorkbook workbook = new XSSFWorkbook()) {
//create your sheets here
workbook.write(fileOut);
return Files.readAllBytes(path);
} catch (Exception e) {
LOG.error("Error during creation of excel report", e);
throw e;
} finally {
if (path != null) {
try {
Files.delete(path);
} catch (final IOException e) {
LOG.error("Unable to delete file:" + path.toString(), e);
}
}
}
}
Write the data to a ByteArrayOutputStream, get the bytes, and use a ByteArrayDataSource to supply the data to JavaMail:
mbp.setDataHandler(new DataHandler(
new ByteArrayDataSource(bytes,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")));
Workbook workbook=new XSSFWorkbook();
Sheet sheet =workbook.createSheet(" ");
Font HearderFont=workbook.createFont();
HearderFont.setBold(true);
HearderFont.setFontHeightInPoints((short)9);
HearderFont.setColor(IndexedColors.RED.getIndex());
CellStyle hearderCellStyle=workbook.createCellStyle();
hearderCellStyle.setFont(HearderFont);
//excel file maker
int rownum=1;
for(MailModelClass mailModelonbj:dataStored) {
Row row=sheet.createRow(rownum++);
row.createCell(0).setCellValue(mailModelonbj.(any));
row.createCell(1).setCellValue(mailModelonbj.(any));
row.createCell(2).setCellValue(mailModelonbj.(any));
}

Is it possable to call a method that takes this.Handle as an argument inside a background worker in C#

I am working on a stand-alone WinForm program in C# that uses the Solidworks EPDM api. The program takes a top level assembly and finds all the referenced and referencing files in the assembly. e.g. all sub-assemblies, part files, and drawings. The program then checks out all the files from EPDM, updates the data cards, and checks in all the files back to the EPDM.
I have successfully implemented the portion of the code that finds all the referenced and referencing files and updates the data card information using a background worker. This portion of the code does not require access the the UI thread. I would like to be able to add the code that checks out the files and checks them back in within a background worker. The problem is that the methods used to do the checkout and check-in take this.Handle as an argument. I know that accessing the UI thread from within a background worker will throw a cross thread exception. The code does not access any of the UI controls. It only need access to this.Handle. Is it possible to pass this.Handle to a background worker in a thread safe way that will not throw a cross thread exception?
This is my first use of background workers so my knowledge is limited. Below is the code that I would like to run in a background worker.
private void BatchCheckout(Dictionary<string, string> SelectedFiles)
{
try
{
IEdmBatchGet batchGetter = (IEdmBatchGet)vault.CreateUtility(EdmUtility.EdmUtil_BatchGet);
EdmSelItem[] ppoSelection = new EdmSelItem[SelectedFiles.Count];
IEdmFile5 aFile;
IEdmFolder5 aFolder;
IEdmFolder5 ppoRetParentFolder;
IEdmPos5 aPos;
int i = 0;
foreach (KeyValuePair<string, string> kvp in SelectedFiles)
{
aFile = vault1.GetFileFromPath(kvp.Key, out ppoRetParentFolder);
aPos = aFile.GetFirstFolderPosition();
aFolder = aFile.GetNextFolder(aPos);
ppoSelection[i] = new EdmSelItem();
ppoSelection[i].mlDocID = aFile.ID;
ppoSelection[i].mlProjID = aFolder.ID;
i = i + 1;
}
batchGetter.AddSelection((EdmVault5)vault1, ref ppoSelection);
batchGetter.CreateTree(this.Handle.ToInt32(), (int)EdmGetCmdFlags.Egcf_Lock);
batchGetter.GetFiles(this.Handle.ToInt32(), null);
}
catch (System.Runtime.InteropServices.COMException ex)
{
MessageBox.Show("HRESULT = 0x" + ex.ErrorCode.ToString("X") + " " + ex.Message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n" + GetStackTrace(ex));
}
}
I have been a reader of StackOverflow for many years and have found answers to just about every question I have ever had. This is my first ever question on StackOverflow. I am really hoping that someone will have an answer to this problem.
EDIT:
I have successfully test AndrewK's suggestion and am happy to report that it did work for my batch checkout method. When I run my batch check-in method in a background worker I'm getting the following COM exception:
Unable to cast COM object of type 'System.__ComObject' to interface type 'EPDM.Interop.epdm.IEdmBatchUnlock2'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{F0970446-4CBB-4F0F-BAF5-F9CD2E09A5B3}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
I only get this exception if I run the code from a background worker.
Here is the code from my BatchCheckin method:
private void BatchCheckin(Dictionary<string, string> SelectedFiles)
{
try
{
int i = 0;
IEdmFolder5 ppoRetParentFolder;
IEdmFile5 aFile;
IEdmFolder5 aFolder;
IEdmPos5 aPos;
EdmSelItem[] ppoSelection = new EdmSelItem[SelectedFiles.Count];
IEdmBatchUnlock2 batchUnlock;
foreach (KeyValuePair<string, string> kvp in SelectedFiles)
{
aFile = vault5.GetFileFromPath(kvp.Key, out ppoRetParentFolder);
aPos = aFile.GetFirstFolderPosition();
aFolder = aFile.GetNextFolder(aPos);
ppoSelection[i] = new EdmSelItem();
ppoSelection[i].mlDocID = aFile.ID;
ppoSelection[i].mlProjID = aFolder.ID;
i = i + 1;
}
batchUnlock = (IEdmBatchUnlock2)vault7.CreateUtility(EdmUtility.EdmUtil_BatchUnlock);
batchUnlock.AddSelection((EdmVault5)vault5, ref ppoSelection);
batchUnlock.CreateTree(0, (int)EdmUnlockBuildTreeFlags.Eubtf_ShowCloseAfterCheckinOption + (int)EdmUnlockBuildTreeFlags.Eubtf_MayUnlock);
batchUnlock.Comment = "Updates";
batchUnlock.UnlockFiles(0, null);
}
catch (System.Runtime.InteropServices.COMException ex)
{
MessageBox.Show("HRESULT = 0x" + ex.ErrorCode.ToString("X") + " " + ex.Message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n" + GetStackTrace(ex));
}
}
I am getting the exception when I make the call to vault7.CreateUtility. The BatchCheckin code is nearly identical to the BatchCheckout. I'm making the same call to vault7.CreateUtility in both methods. The only difference is the EdmUtility flag is set to EdmUtil_BatchUnlock in the BatchCheckin method. Any clue on this one AndrewK?
UPDATE:
I was able to resolve the COM exception by changing batchUpdate from the IEdmBatchUnlock2 interface to the IEdmBatchUnlock interface. Here is the code change:
private void BatchCheckin(Dictionary<string, string> SelectedFiles)
{
int i = 0;
IEdmFolder5 ppoRetParentFolder;
IEdmFile5 aFile;
IEdmFolder5 aFolder;
IEdmPos5 aPos;
EdmSelItem[] ppoSelection = new EdmSelItem[SelectedFiles.Count];
IEdmBatchUnlock batchUnlock = (IEdmBatchUnlock)vault7.CreateUtility(EdmUtility.EdmUtil_BatchUnlock);
try
{
foreach (KeyValuePair<string, string> kvp in SelectedFiles)
{
aFile = vault5.GetFileFromPath(kvp.Key, out ppoRetParentFolder);
aPos = aFile.GetFirstFolderPosition();
aFolder = aFile.GetNextFolder(aPos);
ppoSelection[i] = new EdmSelItem();
ppoSelection[i].mlDocID = aFile.ID;
ppoSelection[i].mlProjID = aFolder.ID;
i = i + 1;
}
batchUnlock.AddSelection((EdmVault5)vault5, ref ppoSelection);
batchUnlock.CreateTree(0, (int)EdmUnlockBuildTreeFlags.Eubtf_ShowCloseAfterCheckinOption + (int)EdmUnlockBuildTreeFlags.Eubtf_MayUnlock);
batchUnlock.Comment = "Release to Production ECO";
batchUnlock.UnlockFiles(0, null);
}
catch (System.Runtime.InteropServices.COMException ex)
{
MessageBox.Show("HRESULT = 0x" + ex.ErrorCode.ToString("X") + " " + ex.Message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n" + GetStackTrace(ex));
}
}
I am guessing that this is a bug in the IEdmBatchUnlock2 interface. The IEdmBatchUnlock2 will cause a COM exception if called from a background worker but will not cause a COM exception if called from the UI thread. The IEdmBatchUnlock interface will not cause a COM exception when called from a background worker.
Just put a 0 in there for the handle. As long as your code will not require user input, it will work. I do it often.
batchGetter.AddSelection((EdmVault5)vault1, ref ppoSelection);
batchGetter.CreateTree(0, (int)EdmGetCmdFlags.Egcf_Lock);
batchGetter.GetFiles(0, null);

BufferedReader is sometimes empty

I have Loader class where I load txt file into BufferedReader from resources and return this field. I use this method but it acts really strange(for me). When I don't put
String str = bufferReader.readLine(); after
bufferReader = new BufferedReader(fileReader);
(in Loader class) than bufferReader in another class is empty, and readLine() returns null. When I write that piece of code in Loader class, I can read each line from txt, except the 1. one which is read in Loader class. Also, I can't read last line if I dont put enter at the end.
public BufferedReader loadFromFileToBufferReader(String fileName) {
ClassLoader classLoader = getClass().getClassLoader();
System.out.print(getClass().getClassLoader().getResource("resources/" + fileName));
File file = new File(classLoader.getResource("resources/" + fileName).getFile());
BufferedReader bufferReader = null;
try (FileReader fileReader = new FileReader(file)) {
bufferReader = new BufferedReader(fileReader);
String str = bufferReader.readLine();
} catch (IOException e) {
System.err.println("Something went terribly wrong with file reading");
}
return bufferReader;
}
and usage:
public Database() {
productsInDatabse = new ArrayList<>();
codesList = new ArrayList<>();
loader = new LoadFromFile();
BufferedReader output = loader.loadFromFileToBufferReader("database.txt");
Product product;
String line;
String[] array;
try {
line = output.readLine();
while (line != null) {
You should paste your code here because it's hard to deduce all the possible causes of this without seeing the code on 100% but I am guessing you have it the same file open at the same time from multiple sources without closing it before from one? Could be literally millions of little things, just telling you how the same error happened to me.

Streamwriter and Streamreader

I have my uni assignment and it's only very basic coding but I have to do
A user shall be able to store records to a file. On start-up a user shall be able to select a file of records and load these into the program.
I am having trouble with this as it will save but once I close the program and re-open it they are gone, any ones help is appreciated.
This is what I have so far:
private void Save_Click(object sender, EventArgs e)
{
SaveToFile(records, file);
}
private void SaveToFile(List<Client> records, string file)
{
//File.WriteAllText(file, String.Empty);
StreamWriter writer = new StreamWriter(file);
StreamReader reader = new StreamReader(file);
try
{
AddMember();
for (int i = 0; i < records.Count; i++)
{
writer.WriteLine(records[i].WriteToFile());
}
writer.Close();
}
catch (IOException z)
{
MessageBox.Show("Error" + z);
}
}
Before closing the StreamWriter you should call Flush() method. Flush() Clears all buffers for the current writer and causes any buffered data to be written to the underlying stream.
reader.clos();
you forgot this
This is just a guess, but it sounds like you might be overwriting the file when you start the program.
In your SaveToFile method, you have the following two lines at the start:
StreamWriter writer = new StreamWriter(file);
StreamReader reader = new StreamReader(file);
The first one will create a new file with the name in file. The second one isn't needed if you're not doing any reading from the file.
Now, if you have a similar block of code in somewhere else in your program that is executed before the SaveToFile method is called, it will overwrite the file (and since you most likely don't write anything in that earlier part of the code, you're left with a blank file).
To prevent this, there are two suggestions I'll offer:
Only create a StreamWriter when you are going to be writing to the file. Any other times you create a StreamWriter, you will be overwriting the existing file.
If you don't want to overwrite the file, you can use the overload of the constructor that takes a second parameter (a boolean) to indicate whether or not to append new data to the file:
StreamWriter writer = new StreamWriter(file, true);
Additionally, I'd suggest getting to know and use using blocks, as this will take care of closing and flushing the StreamWriter (and its underlying stream) for you, even if an exception occurs and is unhandled:
private void SaveToFile(List<Client> records, string file)
{
try
{
AddMember();
// If you don't want to append but overwrite, use:
// using (StreamWriter writer = new StreamWriter(file))
using (StreamWriter writer = new StreamWriter(file, append))
{
for (int i = 0; i < records.Count; i++)
{
writer.WriteLine(records[i].WriteToFile());
}
}
}
catch (IOException z)
{
MessageBox.Show("Error" + z);
}
}

Cannot open a word doc and reference it without locking it

Hello I know how to open and get plain text from a word file for a bit of code. However I am having a bad effect occur from this. The word doc becomes locked and I am not aware how to de allocate whatever is locking it. What I ultimately want would like to open a file that will be in a UNC path and read part of it, whether someone else has it open or not, parse lines from it, close it, don't save anything or lock the file. The closest I can get is I can open a file, parse it, it will lock, but when I open it and close it(same machine running the code) it magically unlocks it.
I know almost nothing on COM so I hunted for a while and found something out about the Marshall object and added that. I have tried to turn on and off the reference 'ReadOnly: True', 'ReadOnly: False'. I feel there is just something simple I am missing so I thought I would ask here. Any suggestions feel free, I am coding in .NET 4.0 so you don't have pass in all those annoying obj = null, obj = null for opening the Doc.
public static string ReadWordDoc(string loc)
{
Word.Application wordApp = new Word.Application();
Word.Document Doc = wordApp.Documents.Open(loc, ReadOnly: true);
sb = "";
foreach (Word.Paragraph objParagraph in Doc.Paragraphs)
{
try
{
sb += objParagraph.Range.Text + "\n";
}
catch (Exception ex)
{
throw ex;
}
}
return sb;
Doc.Close(SaveChanges: false);
Marshal.ReleaseComObject(Doc);
wordApp.Quit(SaveChanges: false);
}
I figured it out for some reason a lock was being kept. I made sure I quit the Word app with 'Do Not Save Changes' as well as running the Garbage Collector as well. It may be a little overkill but it essentially ensures that no lock is left on my file I am targeting.
Word._Application wordApp = new Word.Application();
Word._Document Doc = wordApp.Documents.Open(loc, ReadOnly: true);
try
{
sb = "";
foreach (Word.Paragraph objParagraph in Doc.Paragraphs)
{
try
{
sb += objParagraph.Range.Text + "\n";
}
catch (Exception ex)
{
throw ex;
}
}
}
catch (COMException) { }
finally
{
//FileInfo finfo = new FileInfo(loc);
//finfo.IsReadOnly = false;
if (Doc != null)
{
Doc.Close();
Doc = null;
}
if (wordApp != null)
{
wordApp.Quit(Word.WdSaveOptions.wdDoNotSaveChanges);
wordApp = null;
}
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
return sb;

Resources