คือตอนนี้ ผมเขียนฝัง Server ด้วย Java(รันด้วย Editplus) แล้วตัว Client ก็เขียนด้วย Java (รันด้วย Editplus) สามารถ Connect แล้ว Chat กันไปมาได้ปกติครับ ไม่มีปัญหา

แต่พอผมมาเขียนฝั่ง Client บน Android มันมีปัญหาเกี่ยวกับ Thread ตอนอ่านข้อมูลกลับจากฝั่ง Server ครับตัว Client บน Android สามารถส่งข้อความหา Server ได้ปกติเลครับ

แต่ไม่สามารถอ่าน Buffer จาก Serverได้ มันจะเด้ง Error ถ้าผม Print Log ดูตรง
catch(Exception E){
Log.i(this.toString(), "error : " +E.toString());
}

มันมันจะมีปัญหากับ Class Thread ที่ผมเขียนไว้อ่านข้อมูลจาก Server ครับ แก้มาหลายวันลองมาหลายแบบแล้ว แต่ก็ไม่ได้เรื่องเลย ฝากผู้รู้ หรือเคยเขียน แนะนำ หาทางออกให้ผมที่นะคร้าบบบ

//Code ตอนเรียก Class Theard เพื่อรออ่าน Buffer จาก Server

threadrecieve tr = new threadrecieve(S);
tr.start();

//Code Class threadrecieve

public class threadrecieve extends Thread
{
	Socket SS;
	String msg;
	BufferedReader br;
	threadrecieve(Socket r)
	{
		SS=r;
	}

	public void run()
	{
		try
		{
			System.out.println("rock");
			br = new BufferedReader(new InputStreamReader(SS.getInputStream()));
							while((msg=br.readLine())!=null)
			{				
				projectPCZ.this.mainText.append(msg+"\n"); // Show MSG on Mainboard
				
				if(msg.equals("Server is Shutting Down"))
				{
					userText.setEnabled(true);
					disconnectBtn.setEnabled(false);
					connectBtn.setEnabled(true);
					mainText.setText("");
					serverText.setText("Server is Shutting Down .. .");
					break;
				}
	
			}
			SS.close();
			br.close();
		}
		catch(IOException E){ 
			Log.i(this.toString(), "error: " +E.toString());

		}
	}
}

//Error by Eclipse

Thread [<7> Thread-8] (Suspended (exception

ViewRoot$CalledFromWrongThreadException))

ViewRoot.checkThread() line: 2802

ViewRoot.invalidateChild(View, Rect) line: 607	

ViewRoot.invalidateChildInParent(int[], Rect) line: 633	

TableLayout(ViewGroup).invalidateChild(View, Rect) line: 2505	

TextView(View).invalidate() line: 5139	

TextView.updateAfterEdit() line: 4734	

TextView.handleTextChanged(CharSequence, int, int, int) line: 6158	
TextView$ChangeWatcher.onTextChanged(CharSequence, int, int, int) line: 6316	

SpannableStringBuilder.sendTextChange(TextWatcher[], int, int, int) line: 889	

SpannableStringBuilder.change(boolean, int, int, CharSequence, int, int) line: 352	

SpannableStringBuilder.change(int, int, CharSequence, int, int) line: 269	

SpannableStringBuilder.replace(int, int, CharSequence, int, int) line: 432	

SpannableStringBuilder.append(CharSequence, int, int) line: 259	

SpannableStringBuilder.append(CharSequence, int, int) line: 28	

SpannableStringBuilder(TextView).append(CharSequence, int, int) 

line: 2240

TextView.append(CharSequence) line: 2227	

projectPCZ$threadrecieve.run() line: 173	

//อันนีั้ มัน Error ตอนกด Send อยู่ใน LogChat ของ Android

08-01 10:40:02.604: INFO/global(425): Default buffer size used in BufferedWriter constructor. It would be better to be explicit if an 8k-char buffer is required.

08-01 10:41:00.075: DEBUG/SntpClient(59): request time failed: java.net.SocketException: Address family not supported by protocol

ขอคำแนะนำด้วยนะครับบบบ ทำมาหลายวันแล้วววว

Hiring! บริษัทที่น่าสนใจ

Carmen Software company cover
Carmen Software
Hotel Financial Solutions
Next Innovation (Thailand) Co., Ltd. company cover
Next Innovation (Thailand) Co., Ltd.
We are web design with consulting & engineering services driven the future stronger and flexibility.
KKP Dime company cover
KKP Dime
KKP Dime บริษัทในเครือเกียรตินาคินภัทร
Kiatnakin Phatra Financial Group company cover
Kiatnakin Phatra Financial Group
Financial Service
Fastwork Technologies company cover
Fastwork Technologies
Fastwork.co เว็บไซต์ที่รวบรวม ฟรีแลนซ์ มืออาชีพจากหลากหลายสายงานไว้ในที่เดียวกัน
Thoughtworks Thailand company cover
Thoughtworks Thailand
Thoughtworks เป็นบริษัทที่ปรึกษาด้านเทคโนโยลีระดับโลกที่คว้า Great Place to Work 3 ปีซ้อน
Iron Software company cover
Iron Software
Iron Software is an American company providing a suite of .NET libraries by engineer for engineers.
CLEVERSE company cover
CLEVERSE
Cleverse is a Venture Builder. Our team builds several tech companies.
Nipa Cloud company cover
Nipa Cloud
#1 OpenStack cloud provider in Thailand with our own data center and software platform.
Bangmod Enterprise company cover
Bangmod Enterprise
The leader in Cloud Server and Hosting in Thailand.
CIMB THAI Bank company cover
CIMB THAI Bank
MOVING FORWARD WITH YOU - CIMB is the leading ASEAN Bank
Bangkok Bank company cover
Bangkok Bank
Bangkok Bank is one of Southeast Asia's largest regional banks, a market leader in business banking
MuvMi (Urban Mobility Tech Co.,Ltd.) company cover
MuvMi (Urban Mobility Tech Co.,Ltd.)
Shape the future of urban mobility towards affordable, clean, and safe solutions
T.N. Digital Solution Co., Ltd. company cover
T.N. Digital Solution Co., Ltd.
TNDS has been involving in every first move of banking’s major digital transformation.
KBTG - KASIKORN Business-Technology Group company cover
KBTG - KASIKORN Business-Technology Group
KBTG - "The Technology Company for Digital Business Innovation"
Siam Commercial Bank Public Company Limited company cover
Siam Commercial Bank Public Company Limited
"Let's start a brighter career future together"
Icon Framework co.,Ltd. company cover
Icon Framework co.,Ltd.
Global Standard Platform for Real Estate แพลตฟอร์มสำหรับธุรกิจอสังหาริมทรัพย์ครบวงจร มาตรฐานระดับโลก
REFINITIV company cover
REFINITIV
The Financial and Risk business of Thomson Reuters is now Refinitiv
H LAB company cover
H LAB
Re-engineering healthcare systems through intelligent platforms and system design.
The Gang Technology Co., Ltd. company cover
The Gang Technology Co., Ltd.
We're a Digital Agency that helps our customers transform their business into digital with ease.
LTMH company cover
LTMH
LTMH มุ่งเน้นการพัฒนาผลิตภัณฑ์ที่สามารถช่วยพันธมิตรของเราให้บรรลุเป้าหมาย
Seven Peaks company cover
Seven Peaks
We Drive Digital Transformation
Wisesight (Thailand) Co., Ltd. company cover
Wisesight (Thailand) Co., Ltd.
The Best Choice For Handling Social Media · High Expertise in Social Data · Most Advanced and Secure
MOLOG Tech company cover
MOLOG Tech
We are Modern Logistic Platform, Specialize in WMS, OMS and TMS.
Data Wow Co.,Ltd company cover
Data Wow Co.,Ltd
We enable our clients to realize increased productivity by solving their most complex issues by Data
LINE Company Thailand company cover
LINE Company Thailand
LINE, the world's hottest mobile messaging platform, offers free text and voice messaging + Call
LINE MAN Wongnai company cover
LINE MAN Wongnai
Join our journey to becoming No.1 food platform in Thailand

PaPaSEK Mon, 01/08/2011 - 16:04

ถ้าเข้าใจไม่ผิด... ปัญหามันเกิดจากคุณอ้างถึง Object ที่ถูกสร้างจากคนละ Thread กันครับ

การเรียกข้าม Thread นั้นต้องใช้ Runnable + View.Post ครับ (อ่านเพิ่มเติมตรงนี้)

หรือไม่ก็ต้องใช้ Class android.os.Handler ครับ

เกรงว่าตัวผมเองอธิบายเป็นภาษาคนไม่ได้ดี ผมขอแปะอันนี้ละกันครับ

แบบที่ท่านแนะนำ มันคล้ายๆ ตัวอย่างนี้ หรือปล่าวครับ

ตัวอย่างที่ผมลองใช้ Runable ครับ

ผมก็ลองทำดูแล้ว แบบที่ใช้ Runnable
มันก็ส่งได้อย่างเด่วครับ มันอ่าน Buffer จาก Server ไม่ได้

code ที่ใช้ส่งข้อความไป server ก็ตามนี้ครับ

	if(str.equals("Send")){
		try{
			PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(S                                    
					 .getOutputStream())), true);
			pw.println(msgText.getText());
			pw.flush();
			msgText.setText("");
		}
		catch(Exception E){
			serverText.setText("Error Send :"+E.toString());
		}
	}

ส่วน Code อ่าน Buffer จาก Server ก็ Class ข้างบนครับประมานนั้น

ถ้าเขียนแบบในตัวอย่างถือว่าถูกต้องนะครับ

เพราะสังเกตุได้ว่าตัวอย่างจะมี Handler object อยู่ใน method run ด้วยซึ่ง handler object ตัวนี้เป็น Class ที่จะป้องกันภาวะ Racing (หลาย Thread แย่งกันใช้ resource)

แต่จาก Code ของคุณอันแรก ผมยังไม่เห็นว่าคุณมีการนำอะไรที่เป็นการป้องกัน racing มาใช้เลยครับ

ตัวโปรแกรมที่ผมเขียนครับ
รูปภาพ ตัวโปรแกรม

Console สีดำฝั่งซ้าย เป้น Server ครับ สังเกตุว่า ส่งข้อความหา Server ได้ แต่หน้าจอ Android อ่าน Buffer จาก Server ไม่ได้ ที่เห้นขึ้น XXXXX มันขึ้นก่อนจะเด้งมาฟ้อง Error ข้างล่างของ Eclipse ครับ

คือกดส่งครั้งแรก ไม่ error และขอความหน้าจอ Android ไม่ขึ้น กดรอบสอง ข้อความขึ้นแล้วเด้งไป Error

แต่ก็ยังส่งได้ปกติ

ต้องขอบคุนสำหรับคำแนะนำของท่านจริงๆครับ ตอนนี้ผมสามารถแก้ปัญหานี้ได้แล้วตามคำแนะนำของท่าน
เอะใจตรงที่ท่านบอกว่า " handler object ตัวนี้เป็น Class ที่จะป้องกันภาวะ Racing (หลาย Thread แย่งกันใช้ resource)"

รูปตัวโปรแกรมที่ ใช้งานได้แล้ววว ^^

ที่มันมีปํญหาตอนแรกที่ผมเปลี่ยนมาใช้ Runnable เพราะผมเอา สองส่วนนี้ มาร่วมไว้ใน Runnable เดี่ยวกัน มันเลยเด้งฟ้องทุกครั้งที่ผมกด Send

//ส่วนแรก

mainText.append(msg+"\n"); // Show MSG on Mainboard

//ส่วนสอง

if(msg.equals("Server is Shutting Down"))

{

userText.setEnabled(true);

disconnectBtn.setEnabled(false);

connectBtn.setEnabled(true);

mainText.setText("");

serverText.setText("Server is Shutting Down .. .");

break;

}

ผมเลยลองแยกมันออกมาใหม่ ให้มันอยู่คนล่ะ Runnable ปรากฏว่าใช้ได้
ผมเลยเปลี่ยน TextView เป้น Listview มันจะได้ดูง่ายๆหน่อย

Class สำหรับอ่าน Buffer จาก Server ที่แก้ใหม่ครับ เผื่อใครจะใช้เป้นแนวทาง ..

public class ClientThread implements Runnable {
	
	Socket socket = null;
	String msg;
	BufferedReader br;
	ClientThread(Socket r)
	{
		socket=r;
	}
	public void run() {
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			while ((msg = in.readLine()) != null) {
				Log.d("Server msg: ", msg);
				
				if(msg.equals("Server is Shutting Down"))
				{
					handler.post(new Runnable() {
						@Override
						public void run() {
							userText.setEnabled(true);
							disconnectBtn.setEnabled(false);
							connectBtn.setEnabled(true);
							receivedMessages.add("Server is Shutting Down..");
						}
					});

				}else{
					handler.post(new Runnable() {
						@Override
						public void run() {
							// Show Message in ListView
							receivedMessages.add(msg);
						}
					});
				}
			}
			in.close();
			socket.close();	
			
		} catch (Exception e) {
			handler.post(new Runnable() {
				@Override
				public void run() {
					serverText.setText("Oops. Connection interrupted. Please reconnect your phones.");
				}
			});
			e.printStackTrace();
		}
	}
}

ขอบคุนมากๆครับ

ยินดีครับที่ได้ใช้ความรู้ให้เป็นประโยชน์ ความจริงแล้วผมเพิ่งเคยเขียนแบบ Multi-thread โดยใช้ Handler แค่ครั้งเดียวเองครับ แต่ที่พอจะจำได้เพราะผมแกะ Code ของ Multitouch Keyboard ที่มากับ Gingerbread ครับ

แกะ Code สนุกกว่าเขียนเองเยอะ